單線程非同步 前面幾個例子都是多線程實現的非同步,但是非同步顯然不僅僅是多線程的。我們在之前的例子中使用了Sleep來實現時間的等待,每一個計時器都需要使用一個線程,會導致線程切換頻繁,這個實現效率很低,平常是不會這樣做的。一般游戲邏輯中會設計一個單線程的計時器,我們這裡做一個簡單的實現,用來講解單線程異 ...
單線程非同步
前面幾個例子都是多線程實現的非同步,但是非同步顯然不僅僅是多線程的。我們在之前的例子中使用了Sleep來實現時間的等待,每一個計時器都需要使用一個線程,會導致線程切換頻繁,這個實現效率很低,平常是不會這樣做的。一般游戲邏輯中會設計一個單線程的計時器,我們這裡做一個簡單的實現,用來講解單線程非同步。
// example2_3 class Program { private static int loopCount = 0; private static long time; private static Action action; static void Main(string[] args) { Console.WriteLine($"主線程: {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($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); WaitTimeAsync(4000, WaitTimeAsyncCallback2); } private static void WaitTimeAsyncCallback2() { Console.WriteLine($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); WaitTimeAsync(3000, WaitTimeAsyncCallback3); } private static void WaitTimeAsyncCallback3() { Console.WriteLine($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); } private static void CheckTimerOut() { if (time == 0) { return; } long nowTicks = DateTime.Now.Ticks / 10000; if (time > nowTicks) { return; } time = 0; action.Invoke(); } private static void WaitTimeAsync(int waitTime, Action a) { time = DateTime.Now.Ticks / 10000 + waitTime; action = a; } }
這個例子同樣實現了一個簡單的計時方法,WaitTimeAsync調用時會將回調方法跟時間記錄下來,主線程每幀都會調用CheckTimerOut,CheckTimerOut裡面判斷計時器是否過期,過期了則調用回調方法。整個邏輯都在主線程中完成,同樣是非同步方法。所以非同步並非多線程,單線程同樣可以非同步。上面的例子同樣可以改成await的形式。
// 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($"主線程: {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($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); await WaitTimeAsync(4000); Console.WriteLine($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); await WaitTimeAsync(3000); Console.WriteLine($"當前線程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}"); } private static void CheckTimerOut() { if (time == 0) { return; } long nowTicks = DateTime.Now.Ticks / 10000; if (time > nowTicks) { 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; } }
上面這個例子所有調用全部在主線程中完成,並且使用了await,因此await並不會開啟多線程,await具體用沒用多線程完全取決於具體的實現
ET開源地址地址:egametang/ET: Unity3D Client And C# Server Framework (github.com) qq群:474643097