c#,我怎么知道什么时候我所有的头脑都完成了

本文关键字:我怎么知道 什么时候 | 更新日期: 2023-09-27 18:02:52

我有一个"thread "类,它抛出执行进程的线程。线程在线程类中有一个回调方法,当线程完成时调用该方法。我的问题是,我怎么知道线程器抛出的所有线程都完成了?

c#,我怎么知道什么时候我所有的头脑都完成了

如果你对你已经启动的线程进行计数,你可以在线程启动时增加计数,在线程结束时减少计数。

当计数为0时,你就知道所有的线程都结束了。

在处理寿命较短的线程时,您需要注意确保允许计数器在递减之前递增。需要使用某种锁或Interlocked.IncrementDecrement来修改计数器变量。源

您可以为活动线程的数量保留一个简单的计数器。或者您可以让线程在开始工作之前将自己注册(添加)到集合中,并在完成时删除。

计数工作,但可能比您想象的更难实现…确保在线程内的finally块中进行减量,并同步(lock)对计数器的访问(我知道,它应该是原子的,但是……)。

如果你只创建了一些线程,并有线程实例,你也可以线程。加入每个实例。即使在调用join之前线程已经终止(但仍然是在清理实例之前),这也是有效的。

:

foreach( Thread thread in myThreads)
{
   thread.join();
}

一旦此操作完成,您就可以确定所有线程都已完成。

hth

马里奥

最简单的方法是,如果你事先知道将要运行的线程数,你可以在回调函数中使用计数器。

如果你不知道线程的数量,那么你需要一些"结束处理"指示器来设置一个布尔值,并为创建和结束的线程设置计数器。

如果你不知道将要创建的线程的数量,一个简单的两个计数器的想法是行不通的(如果第一个线程在任何其他线程创建之前开始和结束,它会错误地认为这是最后一个)。

在线程中检查每个线程的状态。如果所有线程都停止(或中止),你知道你可以结束主线程。

您可以使用WaitHandle s。如果你使用BeginInvoke/EndInvoke来控制你的线程,这会变得更有吸引力(因为IAsyncResult带有WaitHandle)。只要记住,在WaitAll调用期间,不要超过操作系统限制的64个项目。下面是一个扩展方法,使这个过程更简单:

static class ThreadingExtensions
{
    // Possible:
    // [ThreadStatic]
    // private static List<WaitHandle> PerThreadWaitList;
    public const int MaxHandlesPerWait = 64;
    public static void WaitAll<T>(this IEnumerable<T> handles, int millisecondsTimeout, int estimatedCount)
        where T : WaitHandle
    {
        // Possible:
        // var currentSet = PerThreadWaitList ?? (PerThreadWaitList = new List<WaitHandle>(estimatedCount));
        var currentSet = new List<WaitHandle>(Math.Min(estimatedCount, MaxHandlesPerWait));
        var timeoutEnd = Environment.TickCount + millisecondsTimeout;
        int timeout;
        // Wait for items in groups of 64.
        foreach (var item in handles)
        {
            currentSet.Add(item);
            if (currentSet.Count == MaxHandlesPerWait)
            {
                timeout = Timeout.Infinite;
                if (millisecondsTimeout >= 0)
                {
                    timeout = timeoutEnd - Environment.TickCount;
                    if (timeout < 0)
                        throw new TimeoutException();
                }
                WaitHandle.WaitAll(currentSet.ToArray(), timeout);
                currentSet.Clear();
            }
        }
        // Do the last set.
        if (currentSet.Count > 0)
        {
            timeout = Timeout.Infinite;
            if (millisecondsTimeout >= 0)
            {
                timeout = timeoutEnd - Environment.TickCount;
                if (timeout < 0)
                    timeout = 0;
            }
            WaitHandle.WaitAll(currentSet.ToArray(), timeout);
            currentSet.Clear();
        }
    }
}

和一个用法的例子。

var results = new List<IAsyncResult>();
// Call delegates, e.g.
// results.Add(Foo.BeginInvoke(OnEndInvokeFoo));
results.Select(x => x.AsyncWaitHandle).WaitAll(Timeout.Infinite, results.Count);

线程计数器的示例代码

long counter = 0;
void ThreadEntryPoint()
{
  try
  {
    ...
    //
  }
  finally
  {
    // Decrement counter
    Interlocked.Decrement(ref counter);
  }
}
void MainThread()
{
  // Start worers
  for(...)
  {
    // Increment threads couter
    Interlocked.Increment(ref counter);
    ((Action)ThreadEntryPoint).BeginInvoke(null, null);
  }
  // Wait until counter is equal to 0
  while(Interlocked.Read(ref counter) != 0)
  {
    Thread.Sleep(0);
  }
}