【问题标题】:How to Kill a task in deadlock situaltion如何在死锁情况下杀死任务
【发布时间】:2020-04-03 08:51:15
【问题描述】:

我正在处理 C# 中的任务。我有一种情况要在Task中运行我的代码。但有时由于某些算法问题,该代码可能会进入死锁状态。 我正在尝试以这样的方式实现等待机制

-我会开始一个任务
- 等待一段时间完成任务执行 -如果任务没有在特定时间执行,我会杀死那个任务

这是我需要实现的。示例代码如下。

问题是即使我取消任务,它也会在没有退出的情况下执行。有人可以帮忙吗?

    public static class MyTest
    {
        public static void StartTask()
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationToken token = tokenSource.Token;
            Task task = new Task(() => TaskMethod(), token);

            task.Start();

            if (!task.Wait(1000))
            {
                tokenSource.Cancel();
                Console.WriteLine("Cancelled");

            }
        }


        public static void TaskMethod()
        {
            while (true)
            {
                Thread.Sleep(2000);

                Console.WriteLine("Haiiiiiii");
            }
        }

    }```

【问题讨论】:

  • 尽量避免杀死任务。这将导致未定义的行为。如果您能详细说明为什么会导致死锁,我们可以与您一起考虑避免发生死锁
  • 如果你遇到了真正的死锁情况,那么你能做的最正确的事情就是将损坏的代码隔离到自己的进程中,然后当你检测到死锁情况时,终止进程。没有强制终止任务的好方法,虽然有终止线程的方法,但它们并不意味着要使用用户代码,所以你不应该。正确的方法是在你的任务中写协同取消,但是这在死锁的情况下可能是没用的,如果你不能修复死锁的bug,就隔离代码,这样你就可以杀死它。
  • 取消任务并不会终止代码执行,它只是表示应该取消任务。在某些情况下,例如如果任务甚至还没有被安排运行,它可能会被框架取消,但如果它已经开始执行,并且肯定会在死锁处停止,取消任务将无济于事。取消是我在其他评论中所写的合作取消概念的一部分,任务代码应该使用取消令牌检查它是否已被取消,如果有则返回/终止。

标签: c# multithreading task


【解决方案1】:

TaskMethod() 必须返回Task,而不是Thread.Sleep() 使用await Task.Delay(),在这种情况下TaskMethod() 必须标记为async

【讨论】:

    【解决方案2】:

    问题不是死锁。您的任务将永远不会响应取消请求。

    任务不会被魔法终止,你应该检查CancellationTokenSourceIsCancellationRequested属性,将其从局部变量更改为字段,这样你的TaskMethod才能访问它。

    试试这个:

    public static class MyTest
    {
        CancellationTokenSource tokenSource = new CancellationTokenSource();
    
        public static void StartTask()
        {
            CancellationToken token = tokenSource.Token;
    
            // Use Task.Run
            Task task = Task.Run(() => TaskMethod(), token);
    
            if (!task.Wait(1000))
            {
                tokenSource.Cancel();
                Console.WriteLine("Cancelled");
    
            }
        }
    
    
        public static void TaskMethod()
        {
            while (!tokenSource.IsCancellationRequested)
            // -----------------^^
            {
                Thread.Sleep(2000);
    
                // optional check:
                if(!tokenSource.IsCancellationRequested)
                    Console.WriteLine("Haiiiiiii");
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多