如何在c#中正确实现等待异步[重复]
Posted
技术标签:
【中文标题】如何在c#中正确实现等待异步[重复]【英文标题】:How to proper implement await async in c# [duplicate] 【发布时间】:2018-11-12 16:37:18 【问题描述】:我是 C# 新手,并且 我正在尝试在 C# 中使用 async 和 await 函数来处理线程和非阻塞 GUI。
这是我目前所拥有的:
public async Task ReadInfo()
string serial;
android.UpdateDeviceList();
if (android.HasConnectedDevices)
serial = android.ConnectedDevices[0];
device = android.GetConnectedDevice(serial);
string model = device.BuildProp.GetProp("ro.product.model");
string bootloader = device.BuildProp.GetProp("ro.bootloader");
string pda = device.BuildProp.GetProp("ro.build.PDA");
addlog("Model : " , Color.White, true, true);
addlog(model, Color.DodgerBlue, true, false);
addlog("Bootloader : ", Color.White, true, true);
addlog(bootloader, Color.DodgerBlue, true, false);
addlog("PDA Version : ", Color.White, true, true);
addlog(pda, Color.DodgerBlue, true, false);
else
addlog("ADB device not found.", Color.Red, true, true);
这是 AddLog 方法:
public void addlog(string s, Color color, bool isBold, bool newline = false)
if (newline)
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.AppendText("\r\n")));
Color selectionColor = color;
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionStart = rtbLog.Text.Length));
rtbLog.BeginInvoke(new MethodInvoker(() => selectionColor = rtbLog.SelectionColor));
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionColor = color));
if (isBold)
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionFont = new Font(rtbLog.Font, FontStyle.Bold)));
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.AppendText(s)));
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionColor = selectionColor));
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.SelectionFont = new Font(rtbLog.Font, FontStyle.Regular)));
rtbLog.BeginInvoke(new MethodInvoker(() => rtbLog.ScrollToCaret()));
在 Button1_Click 我有这个:
private async void Button1_Click(object sender, EventArgs e)
await ReadInfo();
我不知道为什么它会冻结 GUI。
解决问题
变化
public async Task ReadInfo()
到
public void ReadInfo()
并以 button1_click 的身份调用
Task.Run(() => ReadInfo());
【问题讨论】:
使用async
和await
不会神奇地为您创建新线程。此外,由于ReadInfo
上没有单个await
,因此整个方法同步运行。我建议您开始使用官方文档:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
什么是rtbLog
,你为什么要在BeginInvoke
和MethodInvoker
上设置属性?
跨线程调用。
我建议您将ReadInfo
public void ReadInfo
并将您的按钮点击更改为await Task.Run(() => ReadInfo());
。这应该注意不冻结 GUI 并保持代码干净
@CamiloTerevinto 感谢您将其简化为我所期望的答案
【参考方案1】:
ReadInfo
中的任何内容实际上都不是异步的——事实上,编译器应该已经警告过你了。如果没有异步 incomplete 等待,则一切都在当前线程 - UI 线程上继续。
添加async
不会使代码在不同的线程上运行。
【讨论】:
@CamiloTerevinto 甚至await
都没有明确添加任何线程。在这种情况下,我希望应用同步上下文,因此await
是对 UI 线程的回调无论如何
这种场景下如何实现新线程?
@AmanAli 如果您想使用线程:使用线程 - Thread
、ThreadPool.QueueUserWorkItem
或 Task.Run
中的任何一个都应该是不错的候选者
是的,我知道。但令人敬畏的是人们不阅读该方法将同步运行的警告。
我没有看到任何警告。以上是关于如何在c#中正确实现等待异步[重复]的主要内容,如果未能解决你的问题,请参考以下文章