【问题标题】:Thread.Start vs Action in ThreadStartThread.Start 与 ThreadStart 中的操作
【发布时间】:2013-12-20 10:17:24
【问题描述】:

我在更改代码块时遇到了这个问题。

List<Entity> entities = new List<Entity>();
//Some values added to the list ....

foreach(var entity in entities)
{
  Thread th = new Thread(new ThreadStart(SomeMethod));
  th.Start(entity);
}

SomeMethod 正在接受 Entity 并对其进行更改。有点像

private void SomeMethod(Entity entity)
{
  //Some operation on entity
}

这是一个 .NET 2.0 代码,在将其更改为 4.0 时,我做了一个小改动,即

foreach(var entity in entities)
{
  Thread th = new ThreadStart(() => SomeMethod(entity));
  th.Start();
}

这不起作用,从错误看来实体变量在线程之间发生更改并导致一些空引用异常。我没有改变任何其他东西,只要代码恢复到以前的方式,就可以了。谁能解释一下?

【问题讨论】:

  • 这不可能是实际代码,因为ThreadStart 是一个委托,不能转换为Thread。但是,如果您关闭循环变量entity,那么您可能会遇到问题。
  • 你说得对,我现在已经更正了。
  • 你是对的,我现在在两个地方都更正了。现在可以看看吗?
  • 用 ... var obj = entity 尝试过,然后将其作为 SomeMethod(obj) 传递 .. 但没有运气 ... 看起来所有线程都没有开始使用正确的实体对象。

标签: multithreading c#-4.0 delegates


【解决方案1】:

请尝试以这种方式使用新的局部变量:

foreach(var entity in entities)
{
  var copy = entity;
  Thread th = new ThreadStart(() => SomeMethod(copy));
  th.Start();
}

如果您以这种方式引入变量,则使用新变量的方法将不起作用

Thread th = new ThreadStart(() => {var copy = entity; SomeMethod(copy)) };

因为该代码仍将捕获在循环的每次迭代中更改的循环变量。

另外请注意,如果实体集合包含两次相同的元素(即对同一 Entity 对象的两次引用),您可能会收到您描述的错误.请确保不是这种情况。

【讨论】:

    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-08
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多