多线程

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);

 

posted @ 2024-08-13 00:35  你好呀嗯嗯  阅读(16)  评论(0)    收藏  举报