2009-01-12 63 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線程。