我試圖使用CountdownEvent只允許線程在事件的計數爲零時繼續,但是我希望初始計數爲零。實際上,我想返回到零行爲,從而當計數爲零並且線程被設置爲等待大於零時等待該事件。返回零倒數事件
我可以使用0初始計數來初始化倒計時事件,但是當我嘗試添加計數時,我會得到InvalidOperationException「CountdownEvent_Increment_AlreadyZero」。
是否有其他類別或其他方式可以使用Countdown事件以避免此限制?
我試圖使用CountdownEvent只允許線程在事件的計數爲零時繼續,但是我希望初始計數爲零。實際上,我想返回到零行爲,從而當計數爲零並且線程被設置爲等待大於零時等待該事件。返回零倒數事件
我可以使用0初始計數來初始化倒計時事件,但是當我嘗試添加計數時,我會得到InvalidOperationException「CountdownEvent_Increment_AlreadyZero」。
是否有其他類別或其他方式可以使用Countdown事件以避免此限制?
如果您可以將.NET 4.0或Reactive Extensions用於.NET 3.5(它具有.NET 4 TPL功能的反向鏈接),那麼可以查看Barrier類。它允許您協調多個並行任務,以使它們不會繼續,直到障礙中的所有參與者發出信號表示其到達爲止。它也應該滿足您的要求,讓參與者在處理過程中出現和消失。
您寫道:
我執行,這將創建一個未知號碼的孩子操作(沒有任務或線程)
那麼,什麼是他們的工作?你應該做這樣的事情:
CountdownEvent ev; public void foo() { ev = new CountdownEvent(1); foreach (<task in tasks_to_start>) { ev.AddCount(); // enter code here which starts your task } ev.Signal(); ev.Wait(); } public static void youtTask(CountdownEvent ev) { // some work // ... // after all is done ev.Signal(); }
您可以使用一個隊列對象,以「工作」加入到並再次冒了出來。
只有當隊列爲空時,你才能繼續前進。
但是,我們需要細節在這裏...
這會爲你工作嗎? http://msdn.microsoft.com/en-us/library/dd384749.aspx
編輯
對不起,這是模糊的。使用SOReader的答案,如果每個家長都有一個倒計時事件,從1開始 - 然後在孩子中使用TryAddCount遞增,然後將父母遞減回1,然後在孩子完成時從父母遞減到1,最後遞減計數父線程的父代。因此,樹狀系列的倒數事件。
我沒有多線程的經驗,但乍一看這就是我會嘗試。
你的問題似乎是一個常見的樹行走分叉技術。每次你都要遞歸時,你會發起另一個併發操作(將它排入一個線程池等)。但是你需要等待所有子支路結束。只需爲每次啓動的子操作添加1到倒數事件,並在每個子操作結束時發出信號。只要您安排算法,只要它爲每個子操作添加算法,它就不會發出信號,這是安全的。
我應該補充說,你不要需要知道計數前面,只需使它在根1,並且每次你分叉到一個孩子,加1,然後在每個一個,它會動態處理任何樹,沒有前期成本。
CountdownEvent有一個方法添加它可以讓您增加飛行中的計數。
這有道理嗎?我可能會遠離你想要完成的事情。但是,如果您確實需要按照您指定的方式運行的CountdownEvent,則可以很容易地將一些互鎖操作封裝在類中以執行您所說的操作。
但是,CountdownEvent的構建是羽毛重量,如果沒有人在信號發出之前等待,它幾乎是免費的。在昂貴的情況下,它是最優的,無論有多少任務(等),它只會讓一個內核轉換到信號,一個等待,最壞的情況。
爲了實現你的建議,需要圍繞信號和事件重置進行同步。倒計時事件依賴於一個簡單的原則,只有在信號調用中從非零到零的轉換纔可能發出事件信號。沒有競爭,因爲多個線程不可能同時更改值(它是互鎖的),所以只有一個線程可以嘗試發信號通知事件對象(喚醒另一個等待線程)。完善。但是,如果您有多個線程設置並將其重置,則需要同步設置和重置,因爲計數可能會抖動幾次,並且多個線程都會同時嘗試設置或重置事件。 (設置,重置和等待事件都很昂貴,因爲它們都必須進行內核轉換並導致上下文切換)。除非您保護設置/重置轉換,否則它將無法工作。如果他們將此添加到CountdownEvent中,它將不再是幾乎最佳的,它將顯着更昂貴。
你有沒有解決過這個問題?你是怎麼做到的? – HAL9000 2011-04-15 20:31:42