2011-08-18 79 views
0

我在C#中有一個多線程項目,我正在處理這個工作,而我對控制工作線程的想法並不像我希望的那樣容易。在C#中使用監視等待/脈衝線程同步

當打開主界面窗口中創建一個線程,這裏是正在運行的功能:

private void continueReading() 
    { 
     while (true) 
     { 
      lock (_lock) 
      { 
       while (!startDAQ) 
        Monitor.Wait(_lock); 
       startDAQ = false; 
       logging = true; 

       daqTaskComponent1.ReadAsync(); 
      } 
     } 

    } 

現在,當點擊GUI上的按鈕,startDAQ設置爲true,並_lock脈衝啓動線程調用ReadAsync()。

在Async的回調函數中,我鎖定相同的_lock對象並執行一些計算,然後將startDAQ設置爲true並再次脈衝。

這允許我的異步函數僅在回調準備好處理更多數據時才被調用,這就是它的需求。

問題是我需要能夠安全地暫停數據收集,通過導致continueReading線程在Monitor.Wait上暫停,並且通過在暫停之前調用ReadAsync時允許回調完成。

這是當用戶再次點擊按鈕可以暫停數據收集我運行代碼:

lock (_lock) 
    { 
     startDAQ = false; 
     Monitor.PulseAll(_lock); 
     while (logging) 
      Monitor.Wait(_lock); 
    } 

這不能正常工作,我得到一些死鎖。這是我第一次使用Monitor和Wait/Pulsing在線程之間發出信號,所以我一直有點難過,並且有一種感覺,有一種更簡單的方法來處理這個問題。任何幫助或建議表示讚賞。

編輯:這裏是回調函數的相關代碼:

lock (_lock) 
    { 
     //Lots of code here that just manipulates the data passed to the callback 
     startDAQ = true; 
     logging = false; 
     Monitor.PulseAll(_lock); 
    } 

添加日誌布爾值,我忘了,當我最初粘貼我的代碼。

+0

請解釋你的問題是什麼。試圖得到一個合理的錯誤的解決方法運行可能是痛苦的屁股。 – PVitt

+0

問題是我在當前的代碼上遇到了死鎖。我不知道如何讓一個運行循環的線程安全地暫停。我希望用戶能夠單擊按鈕來啓動和停止調用ReadAsync的線程。當用戶停止線程時,我必須執行一些清理操作,這會導致回調函數出現問題,這就是爲什麼我需要任何未完成的ReadAsync在清理髮生之前完成的原因。 – Shaun

+0

startDAQ必須聲明* volatile *。 –

回答

0

爲什麼不直接從GUI線程調用ReadAsync(因爲它已經是異步的),然後從完成回調中再次調用它。沒有其他(顯式的)線程或同步需要。

+0

我想我從來沒有真正理解在哪個上下文中執行回調。他們是在一個新的線程?只是沒有看到一旦啓動後我會中斷調用進程,以便用戶可以暫停數據收集。 – Shaun

+0

回調將在線程池線程的上下文中。要中斷,發出完成回調信號,不要再次調用「ReadAsync」。我建議你用'ManualResetEvent'來做這件事。在回調中,等待事件的超時時間爲0.如果等待失敗,請不要再次調用'ReadAsync'。 –

+0

我試過了你的建議,它在啓動時工作得很好,但我仍然有問題停止。我的按鈕的事件處理程序在異步回調完成之前完成並清理對象,並導致一些空引用錯誤。我試圖設置另一個事件,只有在回調完成時才設置,但我猜事件處理程序和回調函數在同一個線程上執行,因爲一旦我設置了事件處理程序來等待回調,它就會死鎖。 – Shaun