2010-12-07 24 views
4

我使用的是無擴展庫的任務的一部分上的.Net 3.5的Rx Task.Factory.StartNew上的.Net 3.5問題開始兩個任務

它的工作原理主要是順利,但在一個地方,它調用相同的任務兩次。

調用看起來是這樣的:

Task.Factory.StartNew(
    () => Processor.ProcessMessage(incomingMessage), 
    TaskCreationOptions.PreferFairness); 

任何想法?這是一個錯誤?

----更新

我認爲這個問題是與方法C#不lambda表達式中的關閉。 問題WASN「T在TPL,同樣的問題與普通的舊線程池返回

,這解決了它:

foreach (var Processor in processors) 
{ 
object[] crap = new object[2]; 
crap[0] = Processor; 
crap[1] = incomingMessage; 
Task.Factory.StartNew(Magic, crap, TaskCreationOptions.PreferFairness); 
} 

public void Magic(object obj) 
{ 
object[] crap =(object[]) obj; 
((IIncomingMessageProcessor)crap[0]).ProcessMessage((IncomingMessageBase)crap[1]); 
} 

原始來源是:

foreach (var Processor in processors) 
{ 
Task.Factory.StartNew(
    () => Processor.ProcessMessage(incomingMessage), 
    TaskCreationOptions.PreferFairness); 
} 

所以我已經在處理器周圍關閉了,我想問題是它正在爲lambda回收相同的對象並交換處理器。

----更新2

我確信這是問題所在。我重構和調試System.Threading.dll 兩次我創建任務,它是用相同的委託(相同ObjectID)創建的,並且處理器在迭代之間的Target屬性中發生更改。 任何人都知道一個很好的工作?

----更新3 這個工程太(感謝猶大Himango):一個lambda內

foreach (var processor in processors) 
{ 
var crap = processor; 
Task.Factory.StartNew(() => crap.ProcessMessage(incomingMessage), TaskCreationOptions.PreferFairness); 
} 
+1

請嘗試創建一個簡短但完整的程序來演示問題。如果你也可以看到它是否發生在.NET 4上(TPL已經融入到框架本身中),這將會很方便。 – 2010-12-07 15:25:48

+1

也許Processor.ProcessMessage也啓動一個任務? – dtb 2010-12-07 15:25:55

回答

5

是否使用循環變量?例如

foreach (var foo in blah) 
{ 
    // You're capturing foo inside a lambda -- this probably won't do what you think it will! 
    Task.Factory.StartNew(() => foo.Something()); 
} 

參見Why is it bad to use an iteration variable in a lambda expression?

UPDATE 2012年11月:新的C#5的編譯器的地址通過改變行爲,使得foreach循環變量被捕獲時,即,預期的行爲此區域的混亂。 C#團隊的Eric Lippert writes

我們正在採取重大改變。在C#5中,一個 foreach的循環變量將在邏輯上位於循環內部,因此每次關閉變量的新副本時將關閉 。 「for」循環將不會被更改, 。