同步方法api
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 }
运行上面的代码,咱们发现几个问题:并发
一、同步方法卡界面:主线程(UI线程)忙于计算,无暇他顾 ;异步多线程方法不卡界面:主线程闲置,计算任务交给子线程完成异步
二、同步方法慢,只有一个线程计算;async
异步多线程方法快,由于5个线程并发计算 差很少5倍,也不到5倍,CPU密集型计算(资源受限)ide
多线程实际上是资源换性能,1 资源不是无限的 2 资源调度损耗性能
三、同步方法有序进行;this
异步多线程无序spa
启动无序:线程资源是向操做系统申请的,由操做系统的调度策略决定,因此启动顺序随机操作系统
执行时间无序:同一个任务同一个线程,执行时间也不肯定,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