2011-04-09 111 views
0

我有一個C#程序,它有一個「代理程序」類。該程序創建了幾個代理程序,並且每個代理程序都有一個「run()」方法,該方法執行任務(即:Task.Factory.StartNew() ...)。
每個坐席進行一些計算,然後需要等待所有其他坐席完成他們的計算,然後才能進入下一階段(他的行爲將根據其他人的計算)。
爲了讓代理等待,我創建了一個CancellationTokenSource(名爲「tokenSource」),並且爲了提醒程序該代理將要入睡,我拋出了一個事件。因此,連續2個命令是:如何在不發生上下文切換的情況下在線程中執行2個連續的命令?

(1) OnWaitingForAgents(new EventArgs()); 
(2) tokenSource.Token.WaitHandle.WaitOne(); 

(該事件由「AgentManager」類,這是一個線程本身捕獲,並且所述第二命令使代理任務線程休眠直到的信號將被接收用於取消令牌)。

每次觸發上述事件時,AgentManager類都會捕獲該事件,並將+1添加到計數器。如果計數器的數量等於在程序中使用代理的數量,AgentManager(持有的引用,所有代理)喚醒每一個組成如下:

agent.TokenSource.Cancel(); 

現在我們達到我的問題:第一個命令由一個Agent異步執行,然後由於線程之間的上下文切換,AgentManager似乎捕獲該事件,並繼續喚醒所有代理。但是 - 目前的特工還沒有達到第二個命令呢! 因此,特工正在收到一個「喚醒」信號,然後他纔會進入睡眠狀態,這意味着他被卡住而沒有人將他叫醒! 有沒有辦法將兩個連續的方法「原子化」在一起,所以不會發生上下文切換,因此強制代理在AgentManager有機會喚醒他之前進入休眠狀態?

回答

0

humm ...我不認爲這是一個好主意(甚至可能)在.NET中開發軟件時擔心上下文切換,因爲Windows或.NET都不是實時的。該代碼中可能有另一種問題。

我明白你只需要並行運行你所有的代理,並且你想等到所有的代理完成後才能進入下一個階段。您可以使用多種技術來實現這一點,最簡單的方法是使用Monitor.Wait(Object monitor)Monitor.PulseAll(Object monitor)

在任務庫中還有幾件事情要做。正如@jishi指出的那樣,你可以使用Parallel口味,或者產生很多Tasks,然後用Task.WaitAll(Task[] tasks)方法等待所有。

每次上述事件被觸發, 的AgentManager類捕獲它,和 添加1至計數器。

你是如何給計數器加1並且你如何讀它的?您應該使用Interloked.Increment來確保原子操作,並在例如Thread.VolatileRead的易失性操作中讀取它,或者將其置於鎖定語句中。

+0

*基本*擔心在執行低級多線程編程時線程之間的上下文切換。 – 2011-04-12 12:14:14

+0

對於「上下文切換」,我們是否在談論CPU切換到另一個線程上下文x毫秒以提供並行執行的感覺這一事實?你如何從.NET管理它? – vtortola 2011-04-12 15:46:30

1

您提到的低級技術是線程同步。你有什麼關鍵部分(或其中的一部分),你需要保護訪問權限。我很驚訝你已經學會了多線程編程,而沒有了解線程同步和關鍵部分。對於任何種類的「低級」多線程編程來說,瞭解這些內容至關重要。

相關問題