1

I have two functions. i need to start those on a single thread with two sides or on multiple threads, but i want them to be connected so one is terminated, terminate the other one too.

    public static void StartSocket()
    {
        Server myserver = new Server(*, ****);
    }
    public static void StartWeb()
    {
        CreateWebHostBuilder().Build().Run();
    }

Example `

        Thread t1 = new Thread(StartSocket);
        Thread t2 = new Thread(StartWeb);
        t1.Start();
        t2.Start();

how to terminate t1 when t2 is terminated, and t2 when t1 is terminated.

  • What have you tried so far? Also, it would be helpful if you post your code where you actually run the threads. – Robin B Nov 07 '19 at 12:39
  • @RobinB done sir. – Artur_Kamalyan Nov 07 '19 at 12:42
  • Thanks. Ok, so what is exactly meant by termination in your context? Do you want to abort `t2` if `t1` finishes first? Or do you just want to cancel both at the same time if a condition is met? (This should be solved by just calling `Abort()` on both of them.) – Robin B Nov 07 '19 at 12:46
  • Take a look at this: [What's wrong with using Thread.Abort()](https://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort). For a solution, look at [cooperative cancellation](https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads) instead of aborting threads. – Theodor Zoulias Nov 07 '19 at 12:58
  • @TheodorZoulias thanks sir, will look for it now – Artur_Kamalyan Nov 07 '19 at 13:13
  • @RobinB in this case t2 is a web app so it can be terminated by many cases, i just need to know it is canceled or closed – Artur_Kamalyan Nov 07 '19 at 13:14
  • 1
    Have you take a look to that: https://stackoverflow.com/questions/31345481/how-to-stop-one-thread-when-the-other-finishes – Farhad Jabiyev Nov 07 '19 at 13:21
  • If I am right by assuming that `new Server(*,****);` and `CreateWebHostBuilder().Build().Run();` will block execution without you having the chance to somehow signal them to cancel I don't see any easy solution. You most likely want to rewrite both to allow cancelation with a token. It is possible to use `Thread.Abort()` here but you most likely do not want to just drop a thread while it is doing some network stuff. – Robin B Nov 07 '19 at 13:29

2 Answers2

2

As stated in this existing post, the Thread.Abort() is (severely) deprecated.

A most elegant way of doing this would be to use cancellation token on async Tasks.

The only drawback is it does not provide any notifications and you have to monitor it yourself using IsCancellationRequested or ThrowIfCancellationRequested. But on the other hand it is quite handy and easy to accomplish.

A very basic sample:

public class TaskCompletionTests
{
    private readonly ITestOutputHelper _testOutputHelper;
    public TaskCompletionTests(ITestOutputHelper testOutputHelper)
    {
        _testOutputHelper = testOutputHelper;
    }

    [Fact]
    public async Task TerminateOtherWhenOneCompleted()
    {
        // Arrange
        var cancellationSource = new CancellationTokenSource();
        var waitForCompletionDelay = TimeSpan.FromSeconds(2);
        var executionWaitingDelay = TimeSpan.FromSeconds(3);
        var smallerWaitingDelay = TimeSpan.FromSeconds(1);

        // Act
        var taskOne = Task.Run(DoSomething("T1", executionWaitingDelay, cancellationSource), cancellationSource.Token);

        var taskTwo = Task.Run(DoSomething("T2", smallerWaitingDelay, cancellationSource), cancellationSource.Token);

        await Task.WhenAny(taskOne, taskTwo);
        cancellationSource.Cancel();

        await Task.Delay(waitForCompletionDelay);
    }
    
    private Func<Task> DoSomething(string label, TimeSpan waitingDuration, CancellationTokenSource cancellationSource)
    {
        return async () =>
        {
            try
            {
                // do the thing
                _testOutputHelper.WriteLine($"{label} working ...");
                // wait a bit ...
                await Task.Delay(waitingDuration, cancellationSource.Token);
                // checking for cancellation
                cancellationSource.Token.ThrowIfCancellationRequested();
                // do more things ...
                _testOutputHelper.WriteLine($"{label} completed.");
            }
            catch (OperationCanceledException)
            {
                _testOutputHelper.WriteLine($"{label} was aborted");
            }
        };
    }
}

And output will be

T1 working ... T2 working ... T2 completed. T1 was aborted

You can change the wait duration to test that having T1 completed first will also work.

Hopes this helps.

Seb T.
  • 1,104
  • 12
  • 27
  • 1
    Instead of `Thread.Sleep` it is preferable to use [`await Task.Delay`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.delay). As a bonus it accepts a `CancellationToken` as argument. – Theodor Zoulias Nov 10 '19 at 13:44
  • 1
    Thanks @TheodorZoulias I have updated the code based on your feedback. – Seb T. Nov 19 '19 at 08:28
0

It is not adviced to stop a thread with Thread.Abort(), C# Thread Termination and Thread.Abort()

You should have a flag which indicates when you must terminate the thread, for example:

private static bool TerminateThreads = false;

public static void StartSocket()
{
    Server myserver = new Server(*, ****);
    while(!TerminateThreads) 
    { 
        try { ExecuteSomething();  }
        catch { TerminateThreads = true; }
    }
}
public static void StartWeb()
{
    CreateWebHostBuilder().Build().Run();
    while(!TerminateThreads) 
    { 
        try { ExecuteOtherSomething();  }
        catch { TerminateThreads = true; }
    }
}