2.3Single-threaded asynchronous.md 5.1 KB

Single-threaded asynchronous

The previous examples are multi-threaded implementations of asynchrony, but asynchrony is obviously not just multi-threaded. We used Sleep in the previous examples to achieve time waiting, each timer needs to use a thread, which will lead to frequent thread switching, this implementation is very inefficient, usually will not do so. General game logic will design a single-threaded timer, we do a simple implementation here, used to explain single-threaded asynchronous.

    // example2_3
    class Program
    {
        private static int loopCount = 0;

        private static long time;
        private static Action action;
        
        static void Main(string[] args)
        {
            Console.WriteLine($"Main thread: {Thread.CurrentThread.ManagedThreadId}");

            Crontine();
            
            while (true)
            {
                Thread.Sleep(1);

                CheckTimerOut();
                
                ++loopCount;
                if (loopCount % 10000 == 0)
                {
                    Console.WriteLine($"loop count: {loopCount}");
                }
            }
        }
        
        private static void Crontine()
        {
            WaitTimeAsync(5000, WaitTimeAsyncCallback1);
        }

        private static void WaitTimeAsyncCallback1()
        {
            Console.WriteLine($"Current thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount's value is: {loopCount}");
            WaitTimeAsync(4000, WaitTimeAsyncCallback2);
        }
        
        private static void WaitTimeAsyncCallback2()
        {
            Console.WriteLine($"Current thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount's value is: {loopCount}");
            WaitTimeAsync(3000, WaitTimeAsyncCallback3);
        }
        
        private static void WaitTimeAsyncCallback3()
        {
            Console.WriteLine($"Current thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount's value is: {loopCount}");
        }

        private static void CheckTimerOut()
        {
            if (time == 0)
            {
                return;
            }
            long nowTicks = DateTime.Now.Ticks / 10000;
            if (time > nowTicks)
            { return; }
                return;
            }

            time = 0;
            action.Invoke();
        }
        
        private static void WaitTimeAsync(int waitTime, Action a)
        {
            Ticks / 10000 + waitTime;
            action = a;
        }
    }

This example also implements a simple timing method, WaitTimeAsync will be called to record the callback method and time, the main thread will call CheckTimerOut every frame, CheckTimerOut inside to determine whether the timer is expired, expired then callback method is called. The whole logic is done in the main thread, also asynchronously. So asynchronous is not multi-threaded, single-threaded can also be asynchronous. The above example can be changed to await as well.

    // example2_3_2
    class Program
    {
        private static int loopCount = 0;

        private static long time;
        private static TaskCompletionSource<bool> tcs;
        
        static void Main(string[] args)
        {
            Console.WriteLine($"Main thread: {Thread.CurrentThread.ManagedThreadId}");

            Crontine();
            
            while (true)
            {
                Thread.Sleep(1);

                CheckTimerOut();
                
                ++loopCount;
                if (loopCount % 10000 == 0)
                {
                    Console.WriteLine($"loop count: {loopCount}");
                }
            }
        }
        
        private static async void Crontine()
        {
            await WaitTimeAsync(5000);
            Console.WriteLine($"Current thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount's value is: {loopCount}");
            await WaitTimeAsync(4000);
            Console.WriteLine($"Current Thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih The value of loopCount is: {loopCount}");
            await WaitTimeAsync(3000);
            Console.WriteLine($"Current Thread: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih The value of loopCount is: {loopCount}");
        }

        private static void CheckTimerOut()
        {
            if (time == 0)
            {
                return;
            }
            long nowTicks = DateTime.Now.Ticks / 10000;
            if (time > nowTicks)
            { return; }
                return;
            }

            time = 0;
            tcs.SetResult(true);
        }
        
        private static Task WaitTimeAsync(int waitTime)
        {
            TaskCompletionSource<bool> t = new TaskCompletionSource<bool>();
            Time = DateTime.Now.Ticks / 10000 + waitTime;
            tcs = t;
            return t.Task;
        }
    }

The above example all calls are done in the main thread and use await, so await does not open multithreading, await specific use of multithreading depends entirely on the specific implementation