This question already has answers here:
Calling TaskCompletionSource.SetResult in a non blocking manner

(4个答案)


3年前关闭。




我面临着一段我的代码中的僵局问题。值得庆幸的是,我已经能够在下面的示例中重现该问题。作为普通的.Net Core 2.0控制台应用程序运行。
class Class2
{

    static void Main(string[] args)
    {
        Task.Run(MainAsync);
        Console.WriteLine("Press any key...");
        Console.ReadKey();
    }

    static async Task MainAsync()
    {
        await StartAsync();
        //await Task.Delay(1);  //a little delay makes it working
        Stop();
    }


    static async Task StartAsync()
    {
        var tcs = new TaskCompletionSource<object>();
        StartCore(tcs);
        await tcs.Task;
    }


    static void StartCore(TaskCompletionSource<object> tcs)
    {
        _cts = new CancellationTokenSource();
        _thread = new Thread(Worker);
        _thread.Start(tcs);
    }


    static Thread _thread;
    static CancellationTokenSource _cts;


    static void Worker(object state)
    {
        Console.WriteLine("entering worker");
        Thread.Sleep(100);  //some work

        var tcs = (TaskCompletionSource<object>)state;
        tcs.SetResult(null);

        Console.WriteLine("entering loop");
        while (_cts.IsCancellationRequested == false)
        {
            Thread.Sleep(100);  //some work
        }
        Console.WriteLine("exiting worker");
    }


    static void Stop()
    {
        Console.WriteLine("entering stop");
        _cts.Cancel();
        _thread.Join();
        Console.WriteLine("exiting stop");
    }

}

我期望的是完整的序列,如下所示:
Press any key...
entering worker
entering loop
entering stop
exiting worker
exiting stop

但是,实际序列会停在Thread.Join调用上:
Press any key...
entering worker
entering stop

最后,如果我在MainAsync主体中插入一个小的延迟,一切都会很好。
为什么(在哪里)发生僵局?

注意:在原始代码中,我使用SemaphoreSlim而不是TaskCompletionSource解决了,根本没有问题。我只想了解问题出在哪里。

最佳答案

直到基本任务完成后,才会返回tcs.SetResult(null);中的Worker()调用(有关详细信息,请检查this question)。在这种情况下,任务状态为WaitingForActivation,这就是为什么会出现死锁的原因:

  • 调用Worker()会阻止执行tcs.SetResult(null)的线程。
  • 调用Stop()阻止执行_thread.Join()的线程。
  • 关于c# - 是什么导致僵局?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47901988/

    10-09 02:01