ET介绍——单线程异步
1.ET介绍——强大的基于.dotnet7+Unity3d的双端C#开源游戏框架2.ET介绍——为什么使用C# .net core做服务端?3.ET介绍——CSharp协程4.ET介绍——C#更好的协程
5.ET介绍——单线程异步
6.ET介绍——强大的MongoBson库7.ET介绍—— 一切皆实体的设计8.ET介绍——事件机制EventSystem9.ET介绍——组件式设计(优化版的ECS)10.ET介绍——分布式Actor模型11.ET介绍——Actor Location12.ET介绍——数值组件设计13.ET介绍——浅谈AI框架14.ET介绍——更为便捷高效的AI框架-行为机(Behavior Machine)15.ET8开发微信小游戏之部署云服务器Nginx代理16.浅谈ET框架--ECS设计核心(一)17.Dotnet core Console调用WIndows.Forms的MessageBox提示单线程异步
前面几个例子都是多线程实现的异步,但是异步显然不仅仅是多线程的。我们在之前的例子中使用了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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了