Skip to content

Instantly share code, notes, and snippets.

@dlemstra
Created October 5, 2017 06:29
Show Gist options
  • Save dlemstra/390a2a82853bf1dcb34b68fa00d2e940 to your computer and use it in GitHub Desktop.
Save dlemstra/390a2a82853bf1dcb34b68fa00d2e940 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace Deadlock
{
    public class Program
    {
        private static int count = 0;
        private static AutoResetEvent autoResetEvent;

        public static void Main()
        {
            autoResetEvent = new AutoResetEvent(false);

            int maxThreads = 4;
            ThreadPool.SetMaxThreads(maxThreads, 1000);

            for (int i = 0; i < maxThreads; i++)
            {
                // This results in a deadlock
                ThreadPool.QueueUserWorkItem(_ => { SyncAction(); });
             
                // This works
                // ThreadPool.QueueUserWorkItem(async _ => await AsyncAction());
            }

            autoResetEvent.WaitOne();
            while (count != 0)
                autoResetEvent.WaitOne();

            Console.WriteLine("Done");
        }

        private static void SyncAction()
        {
            int index = IncrementCounter();
            WriteLine(index, "Start sync");
            var result = GetHostAddressesAsync().GetAwaiter().GetResult();
            WriteLine(index, "End sync");
            DecrementCounter();
        }

        private static async Task AsyncAction()
        {
            int index = IncrementCounter();
            WriteLine(index, "Start async");
            var result = await GetHostAddressesAsync();
            WriteLine(index, "End async");
            DecrementCounter();
        }

        private static async Task<string> GetHostAddressesAsync()
        {
            var ipAddresses = await Dns.GetHostAddressesAsync("www.microsoft.com");
            return ipAddresses.First().ToString();
        }

        private static int IncrementCounter()
        {
            return Interlocked.Increment(ref count);
        }

        private static void DecrementCounter()
        {
            Interlocked.Decrement(ref count);
            autoResetEvent.Set();
        }

        private static void WriteLine(int index, string text)
        {
            Console.WriteLine(text + "[" + index + "]: " + Thread.CurrentThread.ManagedThreadId);
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment