【问题标题】:Csharp threading starting new threads when one finished without waiting on joinCsharp线程在一个完成时启动新线程而不等待加入
【发布时间】:2011-08-21 20:41:09
【问题描述】:

我已经搜索了一上午,但似乎找不到这个问题的答案。

我有一个线程数组,每个线程都在工作,然后我将循环遍历加入每个线程的 id,然后启动新线程。检测线程何时完成的最佳方法是什么,以便我可以在不等待每个线程完成的情况下触发新线程?

编辑添加代码 sn-p 也许这会有所帮助

            if (threadCount > maxItems)
            {
                threadCount = maxItems;
            }

            threads = new Thread[threadCount];

            for (int i = 0; i < threadCount; i++)
            {
                threads[i] = new Thread(delegate() { this.StartThread(); });
                threads[i].Start();
            }

            while (loopCounter < threadCount)
            {
                if (loopCounter == (threadCount - 1))
                {
                     loopCounter = 0;
                }

                if (threads[loopCounter].ThreadState == ThreadState.Stopped)
                {
                    threads[loopCounter] = new Thread(delegate() { this.StartThread(); });
                    threads[loopCounter].Start();
                }

            }

【问题讨论】:

  • 您使用的是 .NET 4 吗?任务并行库通过延续使这相对容易......

标签: c# multithreading


【解决方案1】:

与其每次都创建新线程,为什么不让每个线程在完成当前 ID 时调用一个返回下一个 ID(如果没有更多数据要处理,则返回 null)的函数?该函数显然必须是线程安全的,但与监视完成的线程并启动新线程相比,应该会减少开销。

所以,

void RunWorkerThreads(int threadCount) {
    for (int i = 0; i < threadCount; ++i) {
        new Thread(() => {
            while(true) {
                var nextItem = GetNextItem();
                if (nextItem == null) break;
                /*do work*/
            }
        }).Start();
    }
}

T GetNextItem() {
   lock(_lockObject) {
       //return the next item
   }
}

我可能会拉出 GetNextItem 并“工作”并将它们作为参数传递给 RunWorkerThreads 以使其更通用 - 所以它会是 RunWorkerThreads&lt;T&gt;(int count, Func&lt;T&gt; getNextItem, Action&lt;T&gt; workDoer),但这取决于你。

请注意,Parallel.ForEach() 本质上是这样做的,但它还提供了监控和中止等方法,因此这里可能没有必要重新发明轮子。

【讨论】:

  • +1 您正在描述一个非常简单的线程池。线程安全可以通过互锁增量来实现。
  • 当然,并且认真地尝试使用 Parallel.For/ForEach 而不是我的快速破解。它更强大。另外,拥有一些经验是一个很好的简历助推器。
【解决方案2】:

您可以检查线程的ThreadState 属性,当它是Stopped 时,您可以启动一个新线程。

http://msdn.microsoft.com/en-us/library/system.threading.thread.threadstate.aspx

http://msdn.microsoft.com/en-us/library/system.threading.threadstate.aspx

【讨论】:

  • 难点是检查状态,特别是什么时候检查。
  • @David Heffernan,您可以使用 ManualResetEvent 在任何线程完成时触发,然后使用 ThreadState 来查看哪个线程。不过确实,有了你提供的附加信息,就没有必要产生新的线程了,按照 Dax 的建议。
【解决方案3】:

让每个线程,作为它做的最后一件事,表示它已经完成。这样就不需要等待了。

更好地转移到更高的抽象级别,例如线程池,让其他人担心这些细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 2012-01-07
    • 1970-01-01
    相关资源
    最近更新 更多