如何在另一个完成时停止一个线程

时间:2015-07-10 16:08:02

标签: c# .net multithreading winforms

我有这段代码

        Thread thread1 = new Thread(this.DoSomething1);
        Thread thread2 = new Thread(this.DoSomething2);
        thread1.Start();
        thread2.Start();

我需要第一个线程完成立即杀死另一个。 请注意,该线程不是那种运行的类型,所以我不能使用静态变量告诉线程停止。哪个帖子会先结束?

4 个答案:

答案 0 :(得分:4)

理想情况下,您希望使用取消令牌或静态变量来安全取消线程。

如果您决定使用cancellationToken / tokenSource:

  var tokenSource = new CancellationTokenSource();
  var token = tokenSource.Token;

  ...

  static void DoSomething1or2(CancellationToken token, CancellationTokenSource tokenSource)
  {

      //Do other work here

      //Since you said neither of your tasks were looping, just put this where
      //you'd want to cancel the thread
      if(token.IsCancellationRequested)
        return; // or token.ThrowIfCancellationRequested();

      //do some more stuff here

      tokenSource.IsCancellationRequested = true;
  }

如果你的doSomething方法是循环的,那么你可以在每个循环的开头或结尾检查一个布尔值,看看是否完成了另一个线程。这种技术与cancellationToken非常相似。

if(otherThreadIsActive && originalCondition)
   {
       //do stuff here
   }

如果您不能等待该次迭代完成,或者无法使用取消令牌,那么我建议您阅读this thread on aborting。除非绝对必要,否则最好不要使用它。

最佳方式:使用取消令牌/ tokenSource

下一个最佳方式:使用某种布尔值来决定何时终止

答案 1 :(得分:1)

Thread用于“启动而忘记”的任务,您可以启动并且不会再次与之交互。如果您需要与某个线程进行交互,例如在它启动后停止它,或者您需要知道线程何时完成,则应使用Task.Run而不是Thread。如果要在任务仍在运行时取消,则需要CancellationTokenSource

var cts = new [] {
    new CancellationTokenSource(),
    new CancellationTokenSource()};
var ts = new[]
{
    Task.Run(() => DoSomething1(cts[0].Token), cts[0].Token),
    Task.Run(() => DoSomething2(cts[1].Token), cts[1].Token)
};

var w = Task.WaitAny(ts);
for (int i = 0; i < cts.Length; i++)
{
    if (i != w) cts[i].Cancel();
}

您的DoSomething必须监控CancellationToken.IsCancellationRequested取消并执行清理。您需要将令牌传递给Task.Run以检测线程是否引发了异常,我还没有证明。有关更多信息,请参阅How to Cancel a Task and Its Children

答案 2 :(得分:0)

你在这些线程中做什么非常重要。如果两者都存在for循环,则可以通过读取循环开始中的共享变量或循环体中的任何位置来停止线程。如果它只是繁重的计算(复杂的业务流程或复杂的数学事物),那么在某事物中间杀死一个线程甚至是危险的。

答案 3 :(得分:0)

我在处理同步线程取消时所做的事情是在类中有一个静态事件来旋转线程。这些线程执行不同类的函数,这些类都监听要触发的静态事件。触发此事件时,在spun up线程执行类中找到volatile private bool _aboutRequested设置为true。在线程执行循环期间,最后完成的任务是检查此退出请求的bool,如果为true,则正常退出。