Я столкнулся с проблемой тупика в части моего кода. К счастью, мне удалось воспроизвести проблему в приведенном ниже примере. Запустите как обычное консольное приложение .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
? - person Groo   schedule 20.12.2017var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
, и он будет работать так, как вы ожидаете. ТеперьSetResult
запускает продолжения синхронно, а продолжение включает вызовStop()
, который сам присоединяется к потоку, в котором выполнялсяSetResult
, поэтому они блокируются. - person Evk   schedule 20.12.2017