委托的多线程方法BeginInvoke

同步方法和异步方法:

同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果。(比如烧水泡茶,需要等水烧开了才能继续泡茶)

异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作。(比如烧水做饭,当水烧着的时候,还可以做饭)

定义一个下载的方法:

private void Download(string filename)
        {
            Console.WriteLine($"开始Download {filename}******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(new Random().Next(5, 10) * 1000);
            Console.WriteLine($"Download {filename} 完成******当前线程:{Thread.CurrentThread.ManagedThreadId}");
        }

使用同步方法调用:

 Console.WriteLine($"下载开始*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            for (int i = 0; i < 3; i++)
            {
                string file = "文件" + i;
                this.Download(file);
            }
            Console.WriteLine($"下载结束*******当前线程:{Thread.CurrentThread.ManagedThreadId}");

输出结果:文件按顺序下载,所有的线程ID都是1

使用异步方法调用:

Console.WriteLine($"下载开始*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Action<string> action = this.Download;
            for (int i = 0; i < 3; i++)
            {
                string file = "文件" + i;
                action.BeginInvoke(file, null, null);
            }
            Console.WriteLine($"下载结束*******当前线程:{Thread.CurrentThread.ManagedThreadId}");

输出结果:文件下载顺序不固定,结束顺序不固定,每个下载都有自己的线程ID。

BeginInvoke 方法用于启动异步调用。它与需要异步执行的方法具有相同的参数,只不过还有两个额外的参数。

BeginInvoke 立即返回,不等待异步调用完成。

EndInvoke 方法用于检索异步调用结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用未完成,EndInvoke 将一直阻塞到

回调方法:

是通过将线程执行后,需要继续执行传入的方法。方法可以自定义。AsyncState为BeginInvoke 传入的第三个object参数。

Console.WriteLine($"下载大文件开始*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Action<string> action = this.Download;
            string file = "流浪地球.MP4";
            AsyncCallback asyncCallback = ar=> {
                Console.WriteLine($"{ar.AsyncState}*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            };

            action.BeginInvoke(file, asyncCallback, "开始播放电影");
            

            Console.WriteLine($"下载大文件结束*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
View Code

 调用结果:

 BeginInvoke 返回值 IasyncResult 

IsComplate 属性等待,通过判断可以知道线程是否已经执行完成。

    Console.WriteLine($"下载大文件开始*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            Action<string> action = this.Download;
            string file = "流浪地球.MP4";
            IAsyncResult asyncResult = null;
            AsyncCallback asyncCallback = ar =>
            {
                Console.WriteLine($"{ar.AsyncState}*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
            };

            asyncResult = action.BeginInvoke(file, asyncCallback, "开始播放电影");
            int i = 0;
            while (!asyncResult.IsCompleted)
            {
                if (i <= 9)
                {
                    Console.WriteLine($"下载了{i * 10}%");
                }
                else
                {
                    Console.WriteLine($"下载了99.99%");
                }
                Thread.Sleep(800);
                i++;
            }
            
            Console.WriteLine($"下载大文件结束*******当前线程:{Thread.CurrentThread.ManagedThreadId}");
View Code

WaitOne等待,即时等待  限时等待

asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成

asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成

asyncResult.AsyncWaitHandle.WaitOne(5000);//最多等待5000ms,超时就不等了

EndInvoke  即时等待,而且可以获取委托的返回值 一个异步操作只能End一次

int iEndResult=action.EndInvoke(asyncResult);//等待某次异步调用操作结束,获取返回值

原文地址:https://www.cnblogs.com/netbatman/p/10464754.html