C# sync/async 同步/异步
同步方法
1 Console.WriteLine($"****************Sync Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 Action<string> action = this.DoSomething; 3 for (int i = 0; i < 5; i++) 4 { 5 string name = string.Format($"Sync_{i}"); 6 action.Invoke(name); //等价 方法直接执行 this.DoSomething(name); 7 } 8 Console.WriteLine($"****************Sync End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
异步方法
1 Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 for (int i = 0; i < 5; i++) 3 { 4 var name = $"Async_{i}"; 5 action.BeginInvoke(name,null,null); 6 } 7 Console.WriteLine($"****************Async End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
1 /// <summary> 2 /// 一个比较耗时耗资源的私有方法 3 /// </summary> 4 private void DoSomething(string name) 5 { 6 Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 7 long lResult = 0; 8 for (int i = 0; i < 1_000_000; i++) 9 { 10 lResult += i; 11 } 12 Thread.Sleep(2000); 13 Console.WriteLine($"****************{name} Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 14 }
运行上面的代码,我们发现几个问题:
1、同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾 ;异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成
2、同步方法慢,只有一个线程计算;
异步多线程方法快,因为5个线程并发计算 差不多5倍,也不到5倍,CPU密集型计算(资源受限)
多线程其实是资源换性能,1 资源不是无限的 2 资源调度损耗
3、同步方法有序进行;
异步多线程无序
启动无序:线程资源是向操作系统申请的,由操作系统的调度策略决定,所以启动顺序随机
执行时间无序:同一个任务同一个线程,执行时间也不确定,CPU分片
结束无序:以上相加,结束也无序
AsyncCallback 异步回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托
AsyncState 用户定义对象:可以作为回调的参数
1 Console.WriteLine($"****************Async Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************"); 2 AsyncCallback callback = ar => Console.WriteLine($"{nameof(AsyncCallback)} 是否完成:{ar.IsCompleted} 用户定义对象:{ar.AsyncState} {Thread.CurrentThread.ManagedThreadId.ToString("00")}"); 3 for (int i = 0; i < 5; i++) 4 { 5 var name = $"Async_{i}"; 6 action.BeginInvoke(name, callback, i); 7 } 8 Console.WriteLine($"****************Async End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
IAsyncResult 对异步调用操作的描述
IsCompleted 判定异步任务是否完成
while (!asyncResult.IsCompleted) //if(!asyncResult.IsCompleted)
{
// Do SomeThing
}
WaitOne 等待,即时等待 限时等待
asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了
EndInvoke 即时等待,而且可以获取委托的返回值 一个异步操作只能End一次
1 Func<int, int> func = Sum; 2 func.BeginInvoke(10, ar => { 3 Console.WriteLine($"线程ID:{ Thread.CurrentThread.ManagedThreadId.ToString("00")} 计算结果:{func.EndInvoke(ar)}"); 4 }, null); 5 6 7 IAsyncResult asyncResult = func.BeginInvoke(5,ar => 8 { 9 //int iEndResultIn = func.EndInvoke(ar); 10 }, null); 11 int iEndResult = func.EndInvoke(asyncResult);
EndInvoke 可以写在BeginInvoke里也可以写在外面 但只能写一次 否则会报错
微软文档:
IAsyncResult:https://docs.microsoft.com/zh-cn/dotnet/api/system.iasyncresult?view=netframework-4.8
AsyncCallback:https://docs.microsoft.com/zh-cn/dotnet/api/system.asynccallback?view=netframework-4.8
作者:德乌姆列特
本博客所有文章仅用于学习、研究和交流目的,欢迎非商业性质转载。
博主的文章没有高度、深度和广度,只是凑字数。由于博主的水平不高,不足和错误之处在所难免,希望大家能够批评指出。
博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的文章,请原谅博主成为一个无耻的文档搬运工!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理