【问题标题】:Is spawning new threads via a LINQ Select call bad code?是否通过 LINQ Select 调用错误代码产生新线程?
【发布时间】:2012-04-28 07:56:08
【问题描述】:

ReSharper 重构了一个 foreach 循环,我不得不这样做。我想通过委托的 BeginInvoke 使用不同的参数生成一堆线程,存储在列表中,并将 IAsyncResults 存储在集合中:

var asyncResults = mylist.Select(x => myDelegate.BeginInvoke(x, null, null));

我的本​​能反应是,这不是一个好习惯。 BeginInvoke 会导致产生新线程的副作用,传递给 Select 的函数不应引起副作用。

或者也许没关系,因为我没有更改调用线程中的任何内容?

【问题讨论】:

  • 在你问自己“这是一个好习惯吗?”之前问问自己“这段代码是否实现了我所描述的行为?”它不是;此代码仅创建一个查询对象。您创建了一个对象,表示“我是从该列表生成一系列异步结果的查询”。 成为该查询不会导致该查询执行。如果您想执行查询并将结果存储在一个集合中,您将不得不编写更多代码。
  • 它自己不会做任何事情,但在某些情况下它可能是合适的。但是,当您调用 BeginInvoke 时,我猜您通常希望线程在此时启动,因此在这种情况下,LINQ 查询与 foreach 循环完全不同。

标签: c# multithreading linq delegates side-effects


【解决方案1】:

应该没问题。创建一个新线程并不是真正的副作用。您没有修改任何值。 BeginInvoke 被调用并且您正在存储生成的 IAsyncResults。

不过,您必须记住,没有什么会阻止。您必须自己管理所有内容的同步。

【讨论】:

    【解决方案2】:

    我认为很难判断这是否是一个好习惯,这取决于你如何使用它。

    但是在像这样使用 LINQ 时要记住的重要一点是,Select()(和许多其他 LINQ 方法)实际上并不遍历集合并执行您的代码。仅当您迭代生成的集合时才会发生这种情况,通常使用foreachToArray()

    【讨论】:

    • 是的,我认为只有当您不介意完全控制线程的确切生成时间时,这才是合适的。我忘记了 LINQ 的懒惰。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多