确保所有线程都退出

Posted

技术标签:

【中文标题】确保所有线程都退出【英文标题】: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 不适合我的情况。

【问题讨论】:

【参考方案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 所说,异步后台工作者更容易实现。

以上是关于确保所有线程都退出的主要内容,如果未能解决你的问题,请参考以下文章

如何退出线程

python threading父进程不死,子线程不退出..如何才能使用完线程后回收线程?

守护线程与普通线程

确保子进程在退出 Python 程序时死亡

主线程创建了子线程,怎么让主线程退出,而子线程仍然运行

守护线程