ET介绍——单线程异步

  • ET介绍——单线程异步已关闭评论
  • 141 次浏览
  • A+
所属分类:.NET技术
摘要

前面几个例子都是多线程实现的异步,但是异步显然不仅仅是多线程的。我们在之前的例子中使用了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