2009-01-12 68 views
0

考虑下面的代码片段:在c#中运行异步操作。 - 基本。

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();     
} 

正如你看到流类是非常简单的。它只有一个正在运行的Threading.Timer。因此,在UI线程上,我必须调用WaitHandle.WaitOne()方法,否则UI线程会结束并因此结束应用程序。

我的目标:由于没有GUI,因此我想创建通知图标。它工作和一切,除了我不能点击它和它没有响应,这是因为它是在UI线程上创建的。我不能把它放在流类中,因为Flow类也在UI线程上(Flow类中的定时器在后台线程中)。

那么在Flow类中运行定时器时如何保持notifyicon响应?我认为waithandle是我的解决方案,但由于其阻塞方法,它不起作用。

任何其他想法/解决方案?

编辑:回复Rich的回答:Flow类在后台线程中,一切都以它应该的方式运行。但是,如果我不在UI线程中添加等待句柄,main()将在UI线程上结束,因此终止整个程序。 (即使在后台线程上启用了定时器)。有另一种解决等待处理的解决方案吗?因为我必须让Flow类去做它的事情。如果我把它拿出来,程序就结束了,如果我把它留在它里面,就会阻塞UI线程,因此我的notifyicon dosnt工作。

回答

0

我字里行间有些在这里,但我认为富是正确的 - 你需要移动后台处理关闭UI线程:

  • 从上面的功能删除form1.dispose通话 - 我想这是你唯一的形式,这就是为什么一旦你处理它的应用程序退出。
  • 异步调用流类 - 执行此操作的最简单方法是调用调用该函数的委托上的ThreadPool.QueueUserWorkItem()(尽管对于长时间运行的操作,您实际上不应该使用线程池线程,但我怀疑它会在这种情况下受到伤害)
  • 一旦流方法完成,回调到UI线程让它知道。您可以通过调用form1.Invoke通过合适的代理来执行此操作。
  • 在随后调用的函数中(即,在UI线程)关闭窗体并退出应用程序

所以最终的结果看起来像3个功能:

  • 上面的功能,它会在后台开始处理,然后无需等待
  • 返回
  • 后台处理功能,在一个单独的线程中执行
  • 称为UI线程上时处理完成的功能,这关闭应用程序
0

我不知道你的Flow对象是什么或它做了什么,但为什么不能在另一个线程中工作而不阻塞UI线程?我认为通知图标是UI的一部分,因此需要在UI线程上,使其成为在另一个线程上运行的错误候选者。相比之下,您的Flow对象似乎正在执行您的应用程序的逻辑,这将在另一个线程上产生更有意义。

+0

嗨,请阅读我的编辑。 – masfenix 2009-01-12 17:57:03

0

活动线程不是标记为后台线程将阻止程序退出。

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(); 

这将创建一个线程,该线程将阻塞,直到你的手柄“保持”是由您的工作线程发出信号,但不会阻止你的UI线程。