public class UnitTest1
{
public async Task TestMethod1Async()
{
Console.WriteLine($"--------------执行同步测试------------------");
Stopwatch watch = new Stopwatch();
watch.Start();//开始监视代码运行时间
//测试代码
var method1Result = method1();
Console.WriteLine($"主线程执行同步method1的返回值:{method1Result}");
var method2Result = method2();
Console.WriteLine($"主线程执行同步method2返回值:{method2Result}");
watch.Stop();//停止监视
var elapsed = watch.Elapsed;//获取当前实例测量得出的总运行时间。
var seconds = elapsed.TotalSeconds; // 总秒数
var milliseconds = elapsed.TotalMilliseconds; // 总毫秒数
Console.WriteLine($"同步结束,总耗时:{milliseconds}");
Console.WriteLine($"--------------执行异步测试,当前线程id:{Thread.GetCurrentProcessorId()}--------------");
watch = new Stopwatch();
watch.Start();//开始监视代码运行时间
var method1AsyncResult = await method1Async();
Console.WriteLine($"主线程执行异步method1Async的返回值:{ method1AsyncResult},当前线程id:{Thread.GetCurrentProcessorId()}");
var result2AsyncResult = await method2Async();
Console.WriteLine($"主线程执行异步method2Async返回值:{result2AsyncResult},当前线程id:{Thread.GetCurrentProcessorId()}");
watch.Stop();//停止监视
elapsed = watch.Elapsed;//获取当前实例测量得出的总运行时间。
seconds = elapsed.TotalSeconds; // 总秒数
milliseconds = elapsed.TotalMilliseconds; // 总毫秒数
Console.WriteLine($"异步总耗时:{milliseconds},当前线程id:{Thread.GetCurrentProcessorId()}");
}
public string method1()
{
Thread.Sleep(1000);
Console.WriteLine("method1 sleep 1000毫秒");
Console.WriteLine("method1执行完毕!");
return "method1";
}
public string method2()
{
Thread.Sleep(2000);
Console.WriteLine("method2 sleep 2000毫秒");
Console.WriteLine("method2执行完毕!");
return "method2";
}
public async Task<string> method1Async()
{
await Task.Run(() =>
{
Thread.Sleep(1000);
Console.WriteLine($"method1Async sleep 1000毫秒,当前线程id:{Thread.GetCurrentProcessorId()}");
});
Console.WriteLine($"method1Async执行完毕!,当前线程id:{Thread.GetCurrentProcessorId()}");
return "method1Async";
}
public async Task<string> method2Async()
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine($"method2Async sleep 2000毫秒,当前线程id:{Thread.GetCurrentProcessorId()}");
});
Console.WriteLine($"method2Async执行完毕!,当前线程id:{Thread.GetCurrentProcessorId()}");
return "method2Async";
}
}
结果:
测试很多次,每次结果都是同步比异步快,采用async和awtia的异步编程方式到底有什么好处??大神能帮科普一下吗?
async/await 只是提高线程的利用率,比如对于 web 应用场景,借助 async/await 可以用50个线程支撑5000个并发
由于额外的上下文切换,async/await 不但没有提速,反而会降速
在高并发以一(线程)敌百(请求)的场景下,async/await 的优势就会体现
为什么会提升并发呢?
比如50个并发进来,如果用同步,就是占用了50个线程而已。
但是如果用异步,可能需要60或100个线程参与进来,这种情况不是更容易导致线程池被用完吗?反而会导致后面的用户访问,因为线程池没有了需要排队等待,这样应该是减少并发才对。
@小智互动: 1000个并发进来,只有50个线程
1)如果用同步,要等每个线程执行完当前请求,才能释放出来处理其他请求
2)如果用异步(await),执行当前请求的线程在遇到异步操作时,先将线程释放出来处理其他请求
比如,你需要做写代码与处理邮件这2件事
1)如果用同步,先写代码,build 代码时在那干等,等写好代码再处理邮件
2)如果用异步(await),也是先写代码,但是在等待build代码的时候用来处理邮件
哪个效率更高?
@dudu:
首选感谢您的回复,但是还有疑问。
如果按你这种需求,用异步的写法代码如下:
public async Task Execute()
{
await WtiteCodeAsync();
await SendMailAsync();
}
SendMailAsync需要等WtiteCodeAsync处理完了再处理,只是可能用了不同线程而已,浪费了一个线程,而且处理时间比同步还要长,所以这种写法提升不了效率吧。
要提示效率应该用下面这种多线程写法,如下:
public void Execute()
{
Task.Run(SendMail);
WtiteCode();
}
把邮件发送丢到其他线程中去处理,这样才能提升效率,而且处理邮件这块不占用主线程,还能让用户明显感觉到减少发送邮件的时间从而提示响应速度。
@小智互动: 下面的代码与我举例想表达的是两回事
await WtiteCodeAsync();
await SendMailAsync();
@小智互动: 不好意思,时间所限,只能回答到这里
线程并不是为了提升单核单线程cpu效率,必须是建立在多线程多核cpu。即使多核多cpu,线程也不是多就效率高,取决于多方面因素。
你这样写测试代码肯定是异步的版本更慢啊,async异步多了线程上下文切换的开销。
可以考虑一下下面的情况
要请求10个或者一百个网页获得这10个或者100个网页的html内容,你用同步和异步比比试试?
或者我要复制10个或者100个文件情况
同步的话,用一个for循环,你请求完一个才能请求另一个(请求第一个时当前干活的线程就会被阻塞,其他啥事也干不了了);异步的话你Task.WhenAll()
,会多线程同时发出n的请求,,速度肯定就上去了;发出网络请求是相对来说耗时的操作,如果发出并接收一个请求要1s,那么同步发出10个就要10s,那我如果同时并发(也就是用async)发出10个或100个呢?在你有多核处理器的时候,肯定是异步快嘛;有点像1个人吃一个馒头要5分钟,10个人吃10个馒头或者一个人吃10个馒头要几分钟的意思;只不过这里的1个馒头变成了发出1个http请求
上面代码都是同步执行的
加了await 表示等待执行结果