我在一段代码中遇到了死锁问题。幸运的是,我已经能够在以下示例中复现该问题。运行为普通的.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
,一切都没有问题。我只想理解问题出在哪里。
Task
和Thread
? - vgruvar tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
,它将按预期运行。现在SetResult
同步运行连续操作,并且连续操作包括对Stop()
的调用,该方法本身会加入执行SetResult
的线程,因此它们会发生死锁。 - Evk