2016-09-30 34 views
-2

這是我的故事:我有wcf服務。它接收到要做的工作。每個任務都被插入到阻塞隊列中。服務器將定期從這個隊列中取出項目並完成工作(在不同的線程中完全異步)。在我的「做」服務中,我需要知道什麼時候「我的」任務完成了。就像這樣:ManualResetEvent對象數組

public bool Do(int input) 
    { 
     // 1. Add task to the BlockingCollection queue 
     // 2. Block this thread from returning and observe/wait til my task is finished 
     return true; 
    } 

這裏是我的建議/解決方案:

public bool Do(int input) 
    { 
     // 1. Create a ManualResetEvent object 
     // 2. Add this object to task 
     // 3. Add task to the BlockingCollection queue 
     // 4. Block this thread from returning - wait for ManualResetEvent object 
     return true; 
    } 

所以,會有因爲有任務做是因爲許多ManualResetEvent的對象。我將從字面上有一個同步對象的數組。這是我的問題的好辦法嗎?

還是有更好的同步類用於我的情況?像等待和脈搏?

感謝您的幫助,

我很抱歉的標題。我不知道如何在標題中提出這個問題。

+0

爲每個任務創建一個類State對象並創建一個List 。將時間和id等屬性放入狀態以及線程對象中。 – jdweng

回答

2

你的計劃是好的,但我建議不要綁定專門的線程等待工作要完成。從new ManualResetEvent(false)切換到new SemephoreSlim(0,1)將允許您使用WaitAsync(),這將允許您在Do方法中使用異步/等待並釋放該線程以執行其他工作。 (更新:這真應了TaskCompletionSource,而不是一個信號量苗條,但我不會更新這個例子,請參見下面的第二部分)

public async Task<bool> Do(int input) 
{ 
    using(var completion = new new SemephoreSlim(0,1)) 
    { 
     var job = new JobTask(input, completion); 
     _workQueue.Add(job); 
     await completion.WaitAsync().ConfigureAwait(false); 
     return job.ResultData; 
    } 
} 

private void ProcessingLoop() 
{ 
    foreach(var job in _workQueue.GetConsumingEnumerable()) 
    { 
     job.PerformWork(); //Inside PerformWork there is a _completion.Release(); call. 
    } 
} 

爲了自給自足的一切都可以改變SemaphoreSlim/TaskCompletionSource並將其放入作業中,然後僅返回作業本身。

​​
+0

謝謝@Scott,但爲什麼我會做「做」異步? 「Do」函數只是向隊列中添加一個項目(一個單一的「int」),並返回......僅此而已。服務器會定期執行一批任務並「執行」。在「添加到隊列」後,我需要等待這個特定的「id」完成。 –

+0

我假設'Do'並不總是返回'true'我認爲'true'來自完成的工作,因此您需要在舊的'ManualResetEvent'中完成'.WaitOne()'代碼在'Do'方法中。如果返回的布爾不是來自工作作業,只是讓它返回'void'。我將以這種方式更新我的答案。 –

+0

謝謝。我添加了'return true',以便wcf客戶端可以在服務器上完成作業(用於他的id)時收到響應。 –