多线程
1.可通过委托的BinginInvoke进行调用:
/// <summary> /// 异步方法 /// 1.同步方法卡界面,主线程忙于计算 /// 异步多线程方法不卡界面,主线程完事了,计算任务交给子线程在做; /// 运用:提升用户体验; /// /// 2.同步方法慢,只有一个线程干活 /// 异步多线程方法快,因为多个线程并发计算 /// 并不是线性增长,1.资源换时间,资源可能不够 2.上下文切换 /// 运用:提升速度,需要多个独立任务可以同时运行 /// /// 3.异步多线程无序:启动无序,执行时间不确定,结束也无序 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnAsync_Click(object sender, EventArgs e) { Console.WriteLine($"************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId}"); Action<string> action = this.DoSomethingLong; for (int i = 0; i < 5; i++) { action.BeginInvoke($"btnAsync_Click_{i}", null, null); } Console.WriteLine($"************btnAsync_Click End {Thread.CurrentThread.ManagedThreadId}"); } private void DoSomethingLong(string name) { Console.WriteLine($"************dosomething {name} Start {Thread.CurrentThread.ManagedThreadId}"); Thread.Sleep(1000); Console.WriteLine($"************dosomething {name} End {Thread.CurrentThread.ManagedThreadId}"); }
2.如果想在异步执行完后,还有事情要做,可传一个回调进去:BeginInvoke中最后的一个参数,就是ia.AsyncState的值,(不会阻塞主线程);
Console.WriteLine($"************btnAsyncAdvanced_Click Start {Thread.CurrentThread.ManagedThreadId}"); Action<string> action = DoSomethingLong; IAsyncResult asyncResult = null; AsyncCallback callback = ia => { Console.WriteLine(object.ReferenceEquals(asyncResult,ia)); Console.WriteLine(ia.AsyncState); Console.WriteLine($"到这里已经计算完成了 {Thread.CurrentThread.ManagedThreadId}"); }; asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "hao");
3.如果想在主线程中等待异步执行完成后,再执行后面的操作,有三种方法(会阻塞主线程)
一.使用IsCompleted进行判断
asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "hao"); int i = 0; while (!asyncResult.IsCompleted)// 1.卡界面:主线程忙于等待 {//可以等待,边等待边做其他操作 //可能最多200ms的延迟 if (i < 10) { Console.WriteLine($"文件上传完成{i++ * 10}%"); } else { Console.WriteLine($"文件上传完成99.999%"); } Thread.Sleep(200); } Console.WriteLine($"文件上传完成了");
二.使用WaitOne()进行等待线程的完成
asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "hao"); asyncResult.AsyncWaitHandle.WaitOne();//等待任务的完成 asyncResult.AsyncWaitHandle.WaitOne(-1);//等待任务的完成, asyncResult.AsyncWaitHandle.WaitOne(1000);//等待,但是最多等待1000ms
三.使用EndInvoke,使用EndInvoke(是将aciton中的逻辑执行完,才会执行主线程或者回调函数中的逻辑)
{ Func<int> func = () => { Thread.Sleep(200); return DateTime.Now.Day; }; Console.WriteLine($"func.Invoke()={func.Invoke()}"); IAsyncResult asyncResult1 = func.BeginInvoke(r => { Console.WriteLine(r.AsyncState); }, "冰封的心"); Console.WriteLine($"func.EndInvoke(asyncResult1)={func.EndInvoke(asyncResult1)}"); }
使用EndInvoke获取异步调用的返回值:如下 b就是异步调用的返回值;
Func<int> func = Dosomething1; func.BeginInvoke((r)=> { var b = func.EndInvoke(r); Console.WriteLine(b); }, null);

浙公网安备 33010602011771号