如何等待线程完成 .NET? [英] How can I wait for a thread to finish with .NET?

查看:43
本文介绍了如何等待线程完成 .NET?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前从未在 C# 中真正使用过线程,我需要有两个线程以及主 UI 线程.基本上,我有以下内容.

I've never really used threading before in C# where I need to have two threads, as well as the main UI thread. Basically, I have the following.

public void StartTheActions()
{
  // Starting thread 1....
  Thread t1 = new Thread(new ThreadStart(action1));
  t1.Start();

  // Now, I want for the main thread (which is calling `StartTheActions` method)
  // to wait for `t1` to finish. I've created an event in `action1` for this.
  // The I wish `t2` to start...

  Thread t2 = new Thread(new ThreadStart(action2));
  t2.Start();
}

所以,本质上,我怎样才能让一个线程等待另一个线程完成?这样做的最佳方法是什么?

So, essentially, how can I have a thread wait for another one to finish? What is the best way to do this?

推荐答案

我可以看到五个可用的选项:

I can see five options available:

就像米奇的回答一样.但这会阻塞您的 UI 线程,但是您会为您内置超时.

As with Mitch's answer. But this will block your UI thread, however you get a Timeout built in for you.

ManualResetEvent 是 jrista 建议的 WaitHandle.

ManualResetEvent is a WaitHandle as jrista suggested.

需要注意的一点是,如果您想等待多个线程:WaitHandle.WaitAll() 默认情况下不起作用,因为它需要一个 MTA 线程.您可以通过使用 MTAThread 标记您的 Main() 方法来解决此问题 - 但是这会阻止您的消息泵,并且我所阅读的内容不推荐使用.

One thing to note is if you want to wait for multiple threads: WaitHandle.WaitAll() won't work by default, as it needs an MTA thread. You can get around this by marking your Main() method with MTAThread - however this blocks your message pump and isn't recommended from what I've read.

请参阅 Jon Skeet 的此页面,了解事件和多线程.有可能在 ifEventName(this,EventArgs.Empty) 之间取消订阅事件 - 我以前也遇到过这种情况.

See this page by Jon Skeet about events and multi-threading. It's possible that an event can become unsubcribed between the if and the EventName(this,EventArgs.Empty) - it's happened to me before.

(希望这些编译通过,我还没试过)

public class Form1 : Form
{
    int _count;

    void ButtonClick(object sender, EventArgs e)
    {
        ThreadWorker worker = new ThreadWorker();
        worker.ThreadDone += HandleThreadDone;

        Thread thread1 = new Thread(worker.Run);
        thread1.Start();

        _count = 1;
    }

    void HandleThreadDone(object sender, EventArgs e)
    {
        // You should get the idea this is just an example
        if (_count == 1)
        {
            ThreadWorker worker = new ThreadWorker();
            worker.ThreadDone += HandleThreadDone;

            Thread thread2 = new Thread(worker.Run);
            thread2.Start();

            _count++;
        }
    }

    class ThreadWorker
    {
        public event EventHandler ThreadDone;

        public void Run()
        {
            // Do a task

            if (ThreadDone != null)
                ThreadDone(this, EventArgs.Empty);
        }
    }
}


4.使用委托

public class Form1 : Form
{
    int _count;

    void ButtonClick(object sender, EventArgs e)
    {
        ThreadWorker worker = new ThreadWorker();

        Thread thread1 = new Thread(worker.Run);
        thread1.Start(HandleThreadDone);

        _count = 1;
    }

    void HandleThreadDone()
    {
        // As before - just a simple example
        if (_count == 1)
        {
            ThreadWorker worker = new ThreadWorker();

            Thread thread2 = new Thread(worker.Run);
            thread2.Start(HandleThreadDone);

            _count++;
        }
    }

    class ThreadWorker
    {
        // Switch to your favourite Action<T> or Func<T>
        public void Run(object state)
        {
            // Do a task

            Action completeAction = (Action)state;
            completeAction.Invoke();
        }
    }
}

如果您确实使用了 _count 方法,那么使用 _count 方法来增加它可能是一个想法(为了安全)

If you do use the _count method, it might be an idea (to be safe) to increment it using

Interlocked.Increment(ref _count)

我很想知道使用委托和事件进行线程通知的区别,我知道的唯一区别是同步调用事件.

I'd be interested to know the difference between using delegates and events for thread notification, the only difference I know are events are called synchronously.

这个问题的答案对您的选项有非常清晰的描述用这种方法.

The answer to this question has a very clear description of your options with this method.

事件/委托的处理方式意味着您的事件处理程序方法在线程1/线程2而不是主UI线程,因此您需要向右切换在 HandleThreadDone 方法的顶部:

The event/delegate way of doing things will mean your event handler method is on thread1/thread2 not the main UI thread, so you will need to switch back right at the top of the HandleThreadDone methods:

// Delegate example
if (InvokeRequired)
{
    Invoke(new Action(HandleThreadDone));
    return;
}

这篇关于如何等待线程完成 .NET?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆