简体   繁体   中英

How to stop one thread when the other finishes

I have this code

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

I need the first thread that finishes to kill the other immediately. Note that the thread is not the kind that runs a while look so I can not use a static variable telling the thread to stop. Which thread will end first?

Ideally you'd want to use a cancellation token or static variable to cancel the thread safely.


If you decide to use the 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;
  }

If your doSomething method is looping then you could check a boolean at the beginning or end of each loop to see whether the other thread is completed. This technique is fairly similar to the cancellationToken.

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

If you can't wait for that iteration to finish, or can't use cancellation token, then I'd suggest reading this thread on aborting . Best not to use it unless it's absolutely necessary.


Best way: use a cancellation token/tokenSource

Next best way: use some sort of boolean to dictate when to terminate

Thread is for 'fire and forget' tasks that you start and never interact with again. If you need to interact with a thread, such as to stop it after it has started, or if you need to know when a thread has finished, you should use Task.Run and not Thread . If you want to cancel a Task while it is still running you need a 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();
}

Your DoSomething s will have to monitor CancellationToken.IsCancellationRequested to cancel and perform cleanup. You need to pass the token to Task.Run to detect if the thread threw an exception, I have not shown that. For more information consult How to Cancel a Task and Its Children .

It is very important what are you doing in those threads. If there is a for loop in both you can stop a thread by reading a shared variable in the beggining of the loop or anywhere in the loop body. If it's just heavy computing (a complex business flow or a complex mathematical thing) it is even dangerous to kill a thread in the middle of something.

What I've done in the past when dealing with syncing thread cancellations is have have a static event in the class that spins up the threads. These threads execute functions of different classes that all listen for this static event to be fired. When this event fires, a volatile private bool _aboutRequested is set to true that is found within the spun up threads execution class. During the thread execution loop, the last thing done is checking this exit requested bool, and if true, gracefully exit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM