我有一个用c#编写的mono应用程序,并使用"mono myapp.exe"在Mac上执行
当从项目属性查看时,应用程序本身是一个"Windows应用程序",但它并不总是显示一个窗口。在program.cs中,有一个静态Main:
static void Main(string[] args) {
UserClient client = new UserClient();
client.Start(args);
}
public class UserClient {
public void Start(string[] args) {
// Talk to server, listen for instructions, etc.
....
// Launch the "Stay Alive" thread
// Just a thread that Sleeps/Loops watching for an exit command; mainly used to keep the process alive
}
}
在UserClient的Start方法中,有一段代码持续监视服务器,并向服务器提供执行操作的指令。它所做的事情之一是使用windows窗体选择性地显示消息。
当服务器指示进程显示消息时,它实例化一个表单,使用frm.ShowDialog()
显示它,然后30秒后,表单上的计时器运行Close(),然后处理form。然而,当这种情况发生时,在我的Mac上,我看到一个应用程序标题栏上写着"mono",并且我的dock栏上出现了一个单声道应用程序的新图标。大约2分钟后,Activity Monitor中的单声道进程显示为"未响应"。这最终将阻止用户退出,关闭等(因为Mac OS不能优雅地杀死mono)。
另一方面……如果服务器从不告诉进程显示该表单,一切都运行得很好:dock图标永远不会显示(这很好!),mono标题栏永远不会显示,mono进程继续愉快地运行,不会阻止系统关闭或重新启动。
有人经历过这种情况吗?或者有人知道是什么原因造成的吗?我的猜测是,这是一个新的GUI线程被创建的形式,从来没有被关闭,并以某种方式导致锁定,虽然我不确定如何处理它。
谢谢你的建议。
更新:
下面是一些代码,可以很容易地重现并查看发生的情况。我意识到这似乎有点"不标准"。话虽如此,下面的程序在Windows环境下完美地工作,并提供了在任务区域中不显示图标的预期结果,除非显示消息。目前,正在使用Application。运行和简单地执行from . showdialog()会产生完全相同的结果。
最后,我们需要的是能够显示表单,然后从dock中销毁表单和任何相关图标。我怀疑GUI正在启动一个从未被处理的线程,这就是为什么dock图标仍然存在。是否有一种方法来确保GUI线程被照顾?
static class Program {
static void Main() {
StartupClass s = new StartupClass();
s.start();
}
}
public class StartupClass {
Thread stayAliveThread;
public void start() {
// Stay alive thread
stayAliveThread = new Thread(stayAliveLoop);
stayAliveThread.Start();
// This shows a form and would normally be used to display temporary and brief messages to the user. Close the message and you'll see the undesired functionality.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Application.Exit();
Application.ExitThread();
}
/// <summary>
/// Keep the app alive.
/// </summary>
private void stayAliveLoop() {
while (true) {
Thread.Sleep(10000);
// In the real project this method monitors the server and performs other tasks, only sometimes displaying a message.
}
}
}
我觉得我错过了几件事。最明显的是
[STAThread]
static void Main(string[] args) { //....
也看这个答案:Windows窗体和ShowDialog问题
我看不到像初始化窗口应用程序的消息循环这样的东西。例如,在windows窗体的情况下,像Application.Run()
。如果你没有它,难怪应用程序冻结。在任何情况下,发布更多的代码可能是有帮助的,正如在评论中所说的。
最后,我无法解决这个问题。我创建了一个进程来启动另一个显示消息表单的应用程序。这不是一个真正的答案,但我必须用这个解决方案。