2017-07-17 56 views
1

考慮我在C#中有一個事件偵聽器,它等待來自串行端口的數據,這些數據一旦通過設置某個狀態捕獲就會返回。在主循環中,我研究了這種狀態,並基於此決定下一步該做什麼。在主線程的睡眠模式下處理從事件處理程序發送的數據C#

爲此,我首先將命令寫入串行端口,並使用Thread.Sleep方法等待輸出。在主線程仍處於睡眠模式時,事件偵聽器已經發送了數據,並且沒有任何事情可以處理這種情況。

任何人都可以請告訴我在這種情況下會有怎樣的結果以及如何預防它?

的代碼會像

bool status = false; 
//main thread 
private void Main() 
{ 

    //some Code 
    serialPort.Write("something"); 

    //Wait for 10 sec 
    Thread.Sleep(10000); 
    while(status == false) 
    { 
     // do something else 
    } 
} 


    //Ignore the syntax, this is just to make people understand 
    public void OndataReceived(object sender, EventArg arg) 
    { 
     //Function that recieve the data 
     Receive(); 

     //change status to true 
     status = true; 

     return; 
    } 
+1

看一看手冊 - 和的AutoResetEvent – Dawnkeeper

+0

創建自定義事件,從'OndataReceived'方法內火了,做在我看來 –

回答

0

問題是笨拙的措辭,但如果我理解正確的話,你問你如何避免數據是否早於接收到的等待十秒鐘。

可以使用較早的同步對象,例如WaitHandle子類之一,Monitor或甚至信號量。但是對於這種情況,目前的C#語言是使用TaskCompletionSource,它提供了一個可等待的對象和同時返回結果值的選項。

例如:

TaskCompletionSource<bool> _result; 

//main thread 
private void Main() 
{ 

    //some Code 
    serialPort.Write("something"); 

    _result = new TaskCompletionSource<bool>(); 

    // Normally, one should "await" a Task. But in the Main() method, which 
    // cannot be "async", we have to just wait synchronously. 
    Task completed = Task.WhenAny(_result.Task, 
     Task.Delay(TimeSpan.FromSeconds(10)).Result; 

    // Don't check "_result.Result" unless the task has completed, 
    // because otherwise the thread will block. If it is completed, 
    // check "_result.Result" as the equivalent to examining the "status" 
    // variable in the previous code example. 
    while(!_result.IsCompleted || !_result.Result) 
    { 
     // do something else 
    } 
} 

public void OndataReceived(object sender, EventArg arg) 
{ 
    //Function that recieve the data 
    Receive(); 

    //change status to true 
    _result.SetResult(true); 

    return; 
} 
+0

感謝彼得在方法中的下一步驟。是的,我想說的是一樣的。但在我的情況下,如果數據是在主線程(由Thread.Start(Main)啓動的主線程)處於睡眠模式時發送的,則整個Windows服務會掛起,因此您的答案可能對我有幫助。還有一件事,我有很多使用Thread.Sleep的地方,使用新的Task對象會比較安全嗎? –

+0

_「我有很多使用Thread.Sleep的地方,是否可以安全地使用新的Task對象?」 - 任何你有'Thread.Sleep()'的地方,你都應該尋找其他的實現(比如如上所述)。 'Thread.Sleep()'方法從來不是一種很好的延遲處理的方法,因爲它阻塞了被調用的線程,現代C#有更好/更有用的方法來完成相同的結果。 –