【问题标题】:Make sure all threads exited确保所有线程都退出
【发布时间】:2011-09-11 08:40:54
【问题描述】:

在一个 win 表单应用程序中,我有一个线程数组,它们是这样启动的:

bool stop = false;
Thread[] threads = new Thread[10];

for (int i = 0; i < threads.Length; i++)
    threads[i] = new Thread(new ThreadStart(Job));

// How to make sure all threads have exited, when the boolean = false

void Job()
{
    while (!stop)
        // Do something
}

现在,如果用户按下 STOP,stop 的布尔值将设置为 true,因此线程一个接一个地退出 Job 方法。如何确保所有线程都已退出?

注意:我的情况需要传统线程,TaskLibrary 不适合我的情况。

【问题讨论】:

    标签: c# multithreading synchronization


    【解决方案1】:

    使用 Join 方法检查是否所有线程都已停止。

     foreach (var t in threads)
     {
         t.Join();
     }
    

    【讨论】:

    • 这段代码放在哪里?这是一个win表单应用程序,UI线程在创建新线程后已经发布。
    • 如果 UI 已经发布,那何必担心呢?但说真的,我会把它放在处理按下停止按钮的方法中。
    • 我想禁止程序退出,直到所有线程都退出。如果用户关闭主窗体并且任务管理器中有一些活动线程,用户会觉得应用程序失败了(尽管所有线程都会在一段时间后退出)
    • @Xaqron:你把这段代码放在你想确保所有线程都完成的地方。
    • @Xaqron:您的问题是我怎样才能确保所有线程都已退出? 我已经回答了。也许你应该问一个适合你的情况的问题!
    【解决方案2】:

    您是否考虑过改用BackgroundWorkers?你说的是“传统线程”..我不太清楚你的意思所以我不知道这是否是一个有效的提议,但无论如何,如果Join() 不能解决你的问题

    BackgroundWorker[] workers = new BackgroundWorker[10];
    bool allThreadsDone = false;
    
    // initialize BackgroundWorkers
    for (int i = 0; i < 10; i++)
    {
            workers[i] = new BackgroundWorker();
            workers[i].WorkerSupportsCancellation = true;
            workers[i].RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            workers[i].DoWork += new DoWorkEventHandler(AlgorithmsUI_DoWork);
            workers[i].RunWorkerAsync();
    }
    
    // thread entry point..DoWork is fired when RunWorkerAsync is called
    void AlgorithmsUI_DoWork(object sender, DoWorkEventArgs e)
    {
          while (!stop)
                // do something        
    }
    
    // this event is fired when the BGW finishes execution
    private void  worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bool threadsStillRunning = false;
        foreach (BackgroundWorker worker in workers)
        {
            if (worker.IsBusy)
            {
                threadsStillRunning = true;
                break;
            }
        }
        if (!threadsStillRunning)
            allThreadsDone = true;
    } 
    
    protected override OnFormClosing(FormClosingEventArgs e)
    {
             if (!allThreadsDone)
             {
                  e.Cancel = true;
                  MessageaBox.Show("Threads still running!");
             }
    }
    

    如果任何线程仍在运行,这应该会阻止您的表单关闭。

    【讨论】:

      【解决方案3】:

      我不确定这是否是您正在寻找的,但这是我在 .NET 3.0 中使用的一个简单解决方案,以确保在继续之前完成大量但确定性的线程:

      全球:

      AutoResetEvent threadPoolComplete = new AutoResetEvent(false);
      static int numThreadsToRun;
      

      当你激活线程时:

      numThreadsToRun = [number of threads];
      [start your threads];
      threadPoolComplete.WaitOne();
      

      在每个线程的代码末尾:

      if (Interlocked.Decrement(ref numThreadsToRun) == 0)
      {
         threadPoolComplete.Set();
      }
      

      【讨论】:

      • + 这是非赢形式类似任务的一个很好的例子。对于 win 表单,正如alexD 所说,异步后台工作者更容易实现。
      猜你喜欢
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-28
      • 2014-07-24
      • 2015-09-18
      • 1970-01-01
      相关资源
      最近更新 更多