翼度科技»论坛 编程开发 .net 查看内容

ET介绍——单线程异步

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
单线程异步

前面几个例子都是多线程实现的异步,但是异步显然不仅仅是多线程的。我们在之前的例子中使用了Sleep来实现时间的等待,每一个计时器都需要使用一个线程,会导致线程切换频繁,这个实现效率很低,平常是不会这样做的。一般游戏逻辑中会设计一个单线程的计时器,我们这里做一个简单的实现,用来讲解单线程异步。
  1.     // example2_3
  2.     class Program
  3.     {
  4.         private static int loopCount = 0;
  5.         private static long time;
  6.         private static Action action;
  7.         
  8.         static void Main(string[] args)
  9.         {
  10.             Console.WriteLine($"主线程: {Thread.CurrentThread.ManagedThreadId}");
  11.             Crontine();
  12.             
  13.             while (true)
  14.             {
  15.                 Thread.Sleep(1);
  16.                 CheckTimerOut();
  17.                
  18.                 ++loopCount;
  19.                 if (loopCount % 10000 == 0)
  20.                 {
  21.                     Console.WriteLine($"loop count: {loopCount}");
  22.                 }
  23.             }
  24.         }
  25.         
  26.         private static void Crontine()
  27.         {
  28.             WaitTimeAsync(5000, WaitTimeAsyncCallback1);
  29.         }
  30.         private static void WaitTimeAsyncCallback1()
  31.         {
  32.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  33.             WaitTimeAsync(4000, WaitTimeAsyncCallback2);
  34.         }
  35.         
  36.         private static void WaitTimeAsyncCallback2()
  37.         {
  38.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  39.             WaitTimeAsync(3000, WaitTimeAsyncCallback3);
  40.         }
  41.         
  42.         private static void WaitTimeAsyncCallback3()
  43.         {
  44.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  45.         }
  46.         private static void CheckTimerOut()
  47.         {
  48.             if (time == 0)
  49.             {
  50.                 return;
  51.             }
  52.             long nowTicks = DateTime.Now.Ticks / 10000;
  53.             if (time > nowTicks)
  54.             {
  55.                 return;
  56.             }
  57.             time = 0;
  58.             action.Invoke();
  59.         }
  60.         
  61.         private static void WaitTimeAsync(int waitTime, Action a)
  62.         {
  63.             time = DateTime.Now.Ticks / 10000 + waitTime;
  64.             action = a;
  65.         }
  66.     }
复制代码
 
这个例子同样实现了一个简单的计时方法,WaitTimeAsync调用时会将回调方法跟时间记录下来,主线程每帧都会调用CheckTimerOut,CheckTimerOut里面判断计时器是否过期,过期了则调用回调方法。整个逻辑都在主线程中完成,同样是异步方法。所以异步并非多线程,单线程同样可以异步。上面的例子同样可以改成await的形式。
  1.     // example2_3_2
  2.     class Program
  3.     {
  4.         private static int loopCount = 0;
  5.         private static long time;
  6.         private static TaskCompletionSource<bool> tcs;
  7.         
  8.         static void Main(string[] args)
  9.         {
  10.             Console.WriteLine($"主线程: {Thread.CurrentThread.ManagedThreadId}");
  11.             Crontine();
  12.             
  13.             while (true)
  14.             {
  15.                 Thread.Sleep(1);
  16.                 CheckTimerOut();
  17.                
  18.                 ++loopCount;
  19.                 if (loopCount % 10000 == 0)
  20.                 {
  21.                     Console.WriteLine($"loop count: {loopCount}");
  22.                 }
  23.             }
  24.         }
  25.         
  26.         private static async void Crontine()
  27.         {
  28.             await WaitTimeAsync(5000);
  29.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  30.             await WaitTimeAsync(4000);
  31.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  32.             await WaitTimeAsync(3000);
  33.             Console.WriteLine($"当前线程: {Thread.CurrentThread.ManagedThreadId}, WaitTimeAsync finsih loopCount的值是: {loopCount}");
  34.         }
  35.         private static void CheckTimerOut()
  36.         {
  37.             if (time == 0)
  38.             {
  39.                 return;
  40.             }
  41.             long nowTicks = DateTime.Now.Ticks / 10000;
  42.             if (time > nowTicks)
  43.             {
  44.                 return;
  45.             }
  46.             time = 0;
  47.             tcs.SetResult(true);
  48.         }
  49.         
  50.         private static Task WaitTimeAsync(int waitTime)
  51.         {
  52.             TaskCompletionSource<bool> t = new TaskCompletionSource<bool>();
  53.             time = DateTime.Now.Ticks / 10000 + waitTime;
  54.             tcs = t;
  55.             return t.Task;
  56.         }
  57.     }
复制代码
 
上面这个例子所有调用全部在主线程中完成,并且使用了await,因此await并不会开启多线程,await具体用没用多线程完全取决于具体的实现
ET开源地址地址:egametang/ET: Unity3D Client And C# Server Framework (github.com)   qq群:474643097

来源:https://www.cnblogs.com/flamesky/archive/2023/05/18/17413679.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具