I ran into a deadlock issue in one piece of code. Fortunately, I was able to reproduce the problem in the example below. Running as a regular .Net Core 2.0 Console application.
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"); } }
What I expect will be the following sequence:
Press any key... entering worker entering loop entering stop exiting worker exiting stop
However, the actual sequence stops when Thread.Join called:
Press any key... entering worker entering stop
Finally, if I insert a slight delay in the body of MainAsync , everything is going well. Why is there a dead end?
NOTE: in the source code, I decided to use SemaphoreSlim instead of TaskCompletionSource , and there are no problems. I just wanted to understand where the problem is.
source share