【问题标题】:How to run two threads together and when one is terminated, automatically terminate other如何一起运行两个线程,当一个线程终止时,自动终止另一个
【发布时间】:2019-11-07 12:28:26
【问题描述】:

我有两个功能。我需要在具有两侧或多个线程的单个线程上启动它们,但我希望它们被连接以便终止一个,也终止另一个。

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

例子`

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

t2终止时如何终止t1,t1终止时如何终止t2。

【问题讨论】:

  • 到目前为止您尝试过什么?此外,如果您将代码发布在您实际运行线程的位置,将会很有帮助。
  • @RobinB 完成,先生。
  • 谢谢。好的,那么在您的上下文中,终止的确切含义是什么?如果t1 先完成,您要中止t2 吗?或者您只是想在满足条件时同时取消两者? (这应该通过调用Abort() 来解决。)
  • 看看这个:What's wrong with using Thread.Abort()。如需解决方案,请查看 cooperative cancellation 而不是中止线程。

标签: c# multithreading


【解决方案1】:

正如existing post 中所述,Thread.Abort() 已(严重)弃用。

最优雅的方法是在async 任务上使用取消令牌。

唯一的缺点是它不提供任何通知,您必须自己使用IsCancellationRequested 或ThrowIfCancellationRequested 对其进行监控。但另一方面,它非常方便且易于完成。

一个非常基本的示例:

[Test]
public void TerminateOtherWhenOneCompleted()
{
    var canceller = new CancellationTokenSource();

    int t1WaitDurationInSeconds = 3;
    int t2WaitDurationInSeconds = 1;

    var taskOne = Task.Run(() =>
    {
        try
        {
            // do the thing
            Console.WriteLine("T1 working ...");
            // wait a bit ...
            await Task.Delay(TimeSpan.FromSeconds(t1WaitDurationInSeconds), canceller.Token);

            // checking for cancellation
            canceller.Token.ThrowIfCancellationRequested();

            // do more things ...
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("T1 was aborted");
        }
    }, canceller.Token);

    var taskTwo = Task.Run(() =>
    {
        try
        {
            // do the thing
            Console.WriteLine("T2 working ...");
            // wait a bit ...
            await Task.Delay(TimeSpan.FromSeconds(t2WaitDurationInSeconds), canceller.Token);

            // checking for cancellation
            canceller.Token.ThrowIfCancellationRequested();

            // do more things ...
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("T2 was aborted");
        }
    }, canceller.Token);

    var completedIndex = Task.WaitAny(taskOne, taskTwo);
    Console.WriteLine($"T{completedIndex+1} completed." );

    canceller.Cancel();
    Task.Delay(TimeSpan.FromSeconds(2)).Wait();
}

输出将是

T1 工作... T2 工作... T2 完成。 T1 被中止

您可以更改等待时间以测试先完成 T1 是否也可以。

希望这会有所帮助。

【讨论】:

  • 最好使用await Task.Delay,而不是Thread.Sleep。作为奖励,它接受 CancellationToken 作为参数。
  • 感谢@TheodorZoulias 我已根据您的反馈更新了代码。
【解决方案2】:

不建议使用 Thread.Abort() 停止线程,C# Thread Termination and Thread.Abort()

你应该有一个标志来表明你什么时候必须终止线程,例如:

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; }
    }
}

【讨论】:

  • 关于TerminateThreads这个静态字段,不应该声明为volatile吗?
  • 那么先生,我将如何创建线程?线程 t1 = 新线程(StartSocket);线程 t2 = 新线程(StartWeb);执行它们。
  • @TheodorZoulias 是的,我不知道,谢谢。
  • @Artur_Kamalyan 您按照自己的方式在类的构造函数上创建这些线程,然后启动它们
猜你喜欢
  • 2014-11-29
  • 2011-12-19
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2011-07-14
  • 1970-01-01
相关资源
最近更新 更多