11 异步多线程(一)

任何的异步多线程,都是和委托相关,没有委托,啥也没有。

BeginInvoke在 C#里面,就是启动一个线程完成任务。

用设置断点的方法来调试的异步多线程,是行不通的,只有多写一些日志或者输出文本信息到控制台程序上。

如果要想看到控制台程序一样的界面输出结果,则在项目上点右键--属性,

同步方法和异步多线程区别:

1.同步方法卡界面,因为UI线程忙于计算;异步多线程不卡界面,主线程闲置,计算任务交给子线程在做。

2.同步方法慢,只有一个线程计算;异步多线程方法快,多个线程并发计算。多线程的资源消耗更多,但线程并不是越多越好(资源有限/管理线程也消耗资源)。具体开多个线程也不是定死的,要通过实际情况。

3.异步多线程是无序的,启动无序,执行时间不确定,结束无序,所以我们不要试图通过启动顺序或者时间等待来控制流程。

看一下这个图:

原因如下:

当多线程运行时,多个请求跑进来问线程池要线程,线程池里面的线程又是通过CLR向操纵系统申请的,哪个请求先拿到线程,要看操作系统分配,线程池掌控不了,所以是无序的。

怎么控制顺序呢?有回调、等待、状态。

1.回调

最推荐的是回调,不卡界面、

Action<string> act = this.DoSomethingLong;
IAsyncResult iAsyncResult = null;
//回调方法
AsyncCallback callback = ar =>
{
    Console.WriteLine(object.ReferenceEquals(ar, iAsyncResult));
    Console.WriteLine(ar.AsyncState);
    Console.WriteLine($"这里是BeginInvoke调用完成之后才执行的。。。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
};
iAsyncResult = act.BeginInvoke("btnAsync_Click", callback, "asyncState");

2.等待

1)IsComplated

Action<string> act = this.DoSomethingLong;
IAsyncResult iAsyncResult = act.BeginInvoke("btnAsync_Click", null, null);

 int i = 1;
//1 卡界面,主线程在等待   2 边等待边做事儿  3有误差
while (!iAsyncResult.IsCompleted)
{
    if (i < 10)
    {
        Console.WriteLine($"文件上传{i++ * 10}%。。。请等待");
    }
    else
    {
        Console.WriteLine("已完成99%。。。马上结束");
    }
    Thread.Sleep(200);
}
Console.WriteLine("文件上传成功!!!");

2)WaitOne

iAsyncResult.AsyncWaitHandle.WaitOne();//一直等待任务完成,第一时间进入下一行
iAsyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成,第一时间进入下一行
iAsyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,否则就进入下一行,可以做一些超时控制

WaitOne用的比较少,它还不如 IsComplated 好用,IsComplated虽然卡界面,但主线程还可以做其他事情,比如输出提示语句。WaitOne卡在那里什么都不能做。

3)EndInvoke,可以获取异步的调用结果

Func<int, string> func = i => i.ToString();
IAsyncResult iAsyncResult = func.BeginInvoke(DateTime.Now.Year, ar =>
{
    string resultIn = func.EndInvoke(ar);//对于每个异步操作,只能调用一次 EndInvoke。
    Console.WriteLine($"This is {ar.AsyncState} 的异步调用结果 {resultIn}");
 }, "小呀么小西瓜");

猜你喜欢

转载自blog.csdn.net/cainong2005/article/details/80531258