请考虑以下代码段:
if(form1.isLoggedIn)
{
//Create a wait handle for the UI thread.
//the "false" specifies that it is non-signalled
//therefore a blocking on the waitone method.
AutoResetEvent hold = new AutoResetEvent(false);
filename = Path.Combine(Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username);
Flow palm = new Flow(new FlowArguments(form1.username, filename), hold);
System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon();
System.Windows.Forms.ContextMenuStrip notificationIconContext = new System.Windows.Forms.ContextMenuStrip();
//Create a context menu strip
ToolStripMenuItem contextAbout = new ToolStripMenuItem("About");
ToolStripMenuItem contextExit = new ToolStripMenuItem("Exit");
//properties of notifyicon that SO dosnt care for including a event handler for the mouse click events.
//wait for the background thread to finish.
hold.WaitOne(Timeout.Infinite);
MessageBox.Show("Thankyou, exiting...");
form1.Dispose();
}
如您所见 FLOW类非常简单。它只有一个Threading.Timer运行。因此在UI线程上我必须调用WaitHandle.WaitOne()方法,因为否则UI线程完成并因此结束应用程序..
我的目标:由于没有GUI,我想创建一个通知图标。它工作和一切,除了我不能点击它并且它没有响应,这是因为它是在UI线程上创建的。我不能把它放在流类中,因为Flow类也在UI线程上(Flow类中的计时器在后台线程中)。
那么在Flow类中运行计时器时如何保持notifyicon的响应?我认为waithandle是我的解决方案但是因为它的阻塞方法它不起作用。
还有其他想法/解决方案吗?
编辑:对Rich的回答的回应:Flow类在后台线程上,一切都以它应该的方式运行。但是如果我不在UI线程中添加waithandle,则main()在UI线程上完成,从而终止整个程序。 (即使在后台线程上启用了计时器)。还有另一种等待手段的解决方案吗?因为我必须让它留给Flow类做它的事情。如果我把它拿出来,程序结束,如果我把它留在它中阻止UI线程因此我的notifyicon dosnt工作。
答案 0 :(得分:0)
我不知道您的Flow对象是什么或它做了什么,但为什么它不能在另一个线程中工作而不阻止UI线程?我认为通知图标是UI的一部分,因此需要在UI线程上使其成为在另一个线程上运行的错误候选者。相比之下,您的Flow对象似乎正在执行您的应用程序的逻辑,这将更有意义在另一个线程上生成。
答案 1 :(得分:0)
标记为后台线程的活动线程不将阻止程序退出。
答案 2 :(得分:0)
我在这里读了一下这些行,但我认为Rich是对的 - 你需要从UI线程中移除后台处理:
所以最终结果看起来像3个函数:
答案 3 :(得分:0)
正如ermau所提到的,前台线程将阻止进程终止。
因此,一种解决方案是更改Flow类,以便它使用前台线程。由于Threading.Timer executes on a ThreadPool thread supplied by the system,你将不得不使用别的东西。
如果您不想修改Flow类,另一个解决方案是创建一个将在句柄上等待的前台线程(除了您的UI线程)。
Thread t = new Thread((ThreadStart)delegate { hold.WaitOne(); });
t.Start();
这将创建一个将阻塞的线程,直到您的工作线程发出“hold”信号,但不会阻止您的UI线程。