11 异步多线程(一)

本文探讨了C#中异步多线程的实现,强调了BeginInvoke在启动线程中的作用。同时指出,调试异步多线程不适合使用断点,而应依赖日志或控制台输出。异步多线程与同步方法的主要区别在于是否阻塞界面和计算速度。线程数量需根据实际需求调整,并且多线程执行顺序不可控。为解决顺序问题,文章提到了回调、等待(IsCompleted和WaitOne)以及EndInvoke作为控制手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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}");
 }, "小呀么小西瓜");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值