Rx Task.Factory.StartNew在.Net 3.5问题上启动两个任务

AK_*_*AK_ 4 .net c# multithreading system.reactive

我正在使用.Net 3.5上的Reactive Extensions库的任务部分

它大部分工作顺利,但在一个地方它调用相同的任务两次.

电话看起来像这样:

Task.Factory.StartNew(
    () => Processor.ProcessMessage(incomingMessage),
    TaskCreationOptions.PreferFairness );
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?这是一个错误吗?

----更新

我认为问题在于c#在lambdas中关闭的方式.问题不在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]);
}
Run Code Online (Sandbox Code Playgroud)

原始来源是:

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

所以我在处理器周围关闭,我想问题是它为lambda回收相同的对象并交换处理器.

----更新2

我确信这是问题所在.我在创建任务时重构和调试了System.Threading.dll,它是使用相同的委托(Same ObjectID)创建的,并且处理器在迭代之间的Target属性中发生了变化.谁知道一个好的工作?

----更新3这也有效(感谢Judah Himango):

foreach (var processor in processors)
{
 var crap = processor;
 Task.Factory.StartNew(() => crap.ProcessMessage(incomingMessage), TaskCreationOptions.PreferFairness);
}
Run Code Online (Sandbox Code Playgroud)

Jud*_*ngo 5

你在lambda中使用循环变量吗?例如

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()); 
}
Run Code Online (Sandbox Code Playgroud)

请参阅为什么在lambda表达式中使用迭代变量不好?

更新2012年11月:新的C#5编译器通过改变捕获foreach循环变量的行为(即预期行为)来解决这一混乱领域.C#团队的Eric Lippert 写道,

我们正在进行重大改变.在C#5中,foreach的循环变量将在逻辑上位于循环内部,因此闭包每次都会关闭变量的新副本."for"循环不会改变.