【问题标题】:How to proper implement await async in c# [duplicate]如何在c#中正确实现等待异步[重复]
【发布时间】:2018-11-12 16:37:18
【问题描述】:

我是 C# 新手,并且 我正在尝试在 C# 中使用 asyncawait 函数来处理线程和非阻塞 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());

【问题讨论】:

  • 使用asyncawait 不会神奇地为您创建新线程。此外,由于ReadInfo 上没有单个await,因此整个方法同步运行。我建议您开始使用官方文档:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
  • 什么是rtbLog,你为什么要在BeginInvokeMethodInvoker 上设置属性?
  • 跨线程调用。
  • 我建议您将ReadInfo public void ReadInfo 并将您的按钮点击更改为await Task.Run(() => ReadInfo());。这应该注意不冻结 GUI 并保持代码干净
  • @CamiloTerevinto 感谢您将其简化为我所期望的答案

标签: c#


【解决方案1】:

ReadInfo 中的任何内容实际上都不是异步的——事实上,编译器应该已经警告过你了。如果没有异步 incomplete 等待,则一切都在当前线程 - UI 线程上继续。

添加async不会使代码在不同的线程上运行。

【讨论】:

  • @CamiloTerevinto 甚至 await 都没有明确添加任何线程。在这种情况下,我希望应用同步上下文,因此await 是对 UI 线程的回调无论如何
  • 这种场景下如何实现新线程?
  • @AmanAli 如果您想使用线程:使用线程 - ThreadThreadPool.QueueUserWorkItemTask.Run 中的任何一个都应该是不错的候选者
  • 是的,我知道。但令人敬畏的是人们不阅读该方法将同步运行的警告。
  • 我没有看到任何警告。
猜你喜欢
  • 2018-02-13
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多