C#   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c# – 为什么Task.Result在这种情况下不起作用?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
它使用以下代码正常工作:

@H_197_7@private void button1_Click(object sender,EventArgs E) { Task<int> t = test(5); Console.WriteLine(t.Result); } private Task<int> test(int n) { return Task.Run(() => { return n; }); }

但是,如果我使用异步方法包装测试方法,它不起作用:

@H_197_7@private Task<int> test(int n) { return Task.Run(() => { return n; }); } public async Task<int> wrap() { return await test(5); } private void button1_Click(object sender,EventArgs E) { Task<int> t = wrap(); Console.WriteLine(t.Result); }

表格失去了回应.如果我使用await,它会按预期工作.

updatE1:
这两个答案都是正确的,但我只能将其标记为答案.基于对这个问题的理解,我做了进一步的测试.我在wrap方法中使用了ConfigureAwait
保留继续在UI以外的线程中运行:

@H_197_7@public async Task<int> wrap() { return await test(5).ConfigureAwait(false); }

它工作正常.然后我测试了这个:

@H_197_7@public async Task<int> wrap() { int i = await test(5).ConfigureAwait(false); int j = i + await test(3); return j; }

它在我第一次单击按钮时工作,但在第二次单击时再次死锁.如果我在test(3)之后添加了ConfigureAwait(false),就像这样:

@H_197_7@public async Task<int> wrap() { int i = await test(5).ConfigureAwait(false); int j = i + await test(3).ConfigureAwait(false); return j; }

它再次运作,但这对我来说没有意义.由于第一个ConfigureAwait(false),wrap()中的所有以下同步部分都应该在非UI线程上运行.我不明白为什么第二个ConfigureAwait(false)是必要的.

updatE2:

@H_197_7@private Task<int> test(int n) { return Task.Run(() => { Console.WriteLine("test(" + n + "): " + System.Threading.Thread.CurrentThread.ManagedThreadId); return n; }); } public async Task<int> wrap() { Console.WriteLine("1.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId); int i = await test(5).ConfigureAwait(false); Console.WriteLine("2.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId); int j = i + await test(3); Console.WriteLine("3.wrap(): " + System.Threading.Thread.CurrentThread.ManagedThreadId); return j; } private void button1_Click(object sender,EventArgs E) { try { Console.WriteLine("1.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId); var t = wrap(); Console.WriteLine("2.button1_Click(): " + System.Threading.Thread.CurrentThread.ManagedThreadId); Console.WriteLine(t.Result); } catch (Exception eX) { Console.WriteLine(ex.messagE); } }

几次单击后,表单冻结,输出为:

@H_197_7@1.button1_Click(): 8 1.wrap(): 8 test(5): 13 2.wrap(): 8 2.button1_Click(): 8 test(3): 13

令我惊讶的是,“2.wrap():”与“1.wrap():”在同一个线程中运行,而不是“test(5)”.似乎ConfigureAwait(false)之后的代码也可以跳回UI线程.

解决方法

这是一个死锁 – 在单线程调度程序中运行的两个任务正在等待彼此完成.

理解这两个非常重要的事情:

>认情况下,await的结果返回到与其开始时相同的调度程序.
> UI在单线程事件循环上运行,并且在UI@L_801_29@中可用于等待的立即调度程序是调度到此事件循环的调度程序.在此调度程序中,一次只能执行一个Task.

因此,您需要特别注意如何在UI调度程序内部执行的Task上@L_801_29@阻塞方法.

在第二个示例中,对Result的@L_801_29@正在等待包装中的继续设置完成.延迟计划在UI线程上运行,对Result的@L_801_29@恰好是阻塞,因此两者都不会完成.

大佬总结

以上是大佬教程为你收集整理的c# – 为什么Task.Result在这种情况下不起作用?全部内容,希望文章能够帮你解决c# – 为什么Task.Result在这种情况下不起作用?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。