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

发布于 2024-10-06 22:35:45 字数 1338 浏览 0 评论 0原文

我正在 .Net 3.5 上使用反应式扩展库的任务部分,

它工作起来大部分都很顺利,但在一个地方它调用同一任务两次。

通话内容如下:

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

有什么想法吗?这是一个错误吗?

---- 更新

我认为问题在于 c# 在 lambda 中执行闭包的方式。 问题不在 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

我确信这就是问题所在。 我两次创建任务时,都是使用相同的委托(相同的 ObjectID)创建的,并且处理器在迭代之间的目标属性中发生变化。 有人知道有什么好的解决办法吗?

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

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

I'm using the tasks part of the Reactive Extensions library on .Net 3.5

It works mostly smoothly but in one place it calls the same task twice.

The call looks like this:

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

Any ideas? Is this a bug?

---- update

i think the problem is with the way c# does closure in lambdas.
the problem wasn"t in the TPL, the same problem returned with the plain old thread pool.

and this solved it:

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]);
}

the original source was:

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

so i have closure around Processor, and i guess the problem was it was recycling the same object for the lambda and swapping the Processor.

---- update 2

I'm convinced this is the problem. i refactored and debugged the System.Threading.dll
both times i create the task, it is created with the same delegate(Same ObjectID) and the Processor changes in the Target property between iterations.
anyone knows a good work around?

---- update 3
this works too(thanks Judah Himango):

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

憧憬巴黎街头的黎明 2024-10-13 22:35:45

您是否在 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()); 
}

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

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

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

Are you using loop variables inside a lambda? e.g.

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()); 
}

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

UPDATE November 2012: The new C# 5 compiler addresses this area of confusion by changing the behavior such that the foreach loop variable is captured, i.e. the expected behavior. Eric Lippert of the C# team writes,

We are taking the breaking change. In C# 5, the loop variable of a
foreach will be logically inside the loop, and therefore closures will
close over a fresh copy of the variable each time. The "for" loop will
not be changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文