在C#中同步线程

时间:2014-01-07 06:48:11

标签: c# .net multithreading

我有一个基于表单的应用程序。 UI由线程处理。 从UI线程中,我创建了3个线程来执行一些处理。

Thread t1 = new Thread(() => performprocessing());
Thread t2 = new Thread(() => performprocessing());
Thread t3 = new Thread(() => performprocessing());

现在,我想在所有3个线程完成执行后在UI线程中执行一条语句。所以,我做了以下事情:

do 
{

} while (t1.IsAlive || t2.IsAlive || t3.IsAlive);
/*--execute statement---*/

但我希望UI能够保持响应。在这种情况下,UI线程停留在循环中,直到所有三个线程完成执行。 我该怎么做?

我读过有关手动和自动重置事件但我不确定如何在这种情况下使用它们。 请指导我。

4 个答案:

答案 0 :(得分:5)

尝试使用Barrier

您需要将Barrier实例传递到您的线程中,然后在线程中使用Barrier.SignalAndWait()。在Barrier的构造函数中指定您需要继续的信号数。

收到所有信号后,正在等待的线程将停止阻塞。

答案 1 :(得分:2)

产生新线程是一种不好的做法,而是使用线程池。

{
    var t1 = Task.Run(() => doSomething1());
    var t2 = Task.Run(() => doSomething2());
    var t3 = Task.Run(() => doSomething3());

    Task.WhenAll(t1, t2, t3).ContinueWith(t => doSomething4());
}

.NET 4.5的更简洁方法是使用async / await。

async void Form1_Load(object sender, EventArgs e)
{ 
    var t1 = Task.Run(() => doSomething1());
    var t2 = Task.Run(() => doSomething2());
    var t3 = Task.Run(() => doSomething3());

    await Task.WhenAll(t1, t2, t3);
    doSomething4();
}

.NET 4.0没有定义Task.Run()和Task.WhenAll(),而是使用Task.Factory。

{
    var t1 = Task.Factory.StartNew(() => doSomething1());
    var t2 = Task.Factory.StartNew(() => doSomething2());
    var t3 = Task.Factory.StartNew(() => doSomething3());

    Task.Factory.ContinueWhenAll(new[] { t1, t2, t3}, tasks => doSomething4());
}

答案 2 :(得分:0)

使用后台工作线程,您可以保持ui响应并发送进度。

void Form1_Load(object sender, EventArgs e)
        {
            BackgroundWorker b1 = new BackgroundWorker();
            BackgroundWorker b2 = new BackgroundWorker();
            BackgroundWorker b3 = new BackgroundWorker();
            b1.RunWorkerCompleted += b1_RunWorkerCompleted;
            b2.RunWorkerCompleted += b2_RunWorkerCompleted;
            b3.RunWorkerCompleted += b3_RunWorkerCompleted;
        }

        void b1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        void b2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

        void b3_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }

答案 3 :(得分:-1)

如果由于某种原因您不希望使用solmaks提到的Task,那么您可以使用Join()方法,该方法将阻塞直到线程完成。

Thread t1 = new Thread(() => performprocessing());
Thread t2 = new Thread(() => performprocessing());
Thread t3 = new Thread(() => performprocessing());

t1.Join();
t2.Join();
t3.Join();

我不建议在UI线程上使用它,因为它可能会使您的应用程序无响应。