【问题标题】:Async/Await with a WinForms ProgressBar - WinForms version带有 WinForms ProgressBar 的 Async/Await - WinForms 版本
【发布时间】:2023-03-09 15:05:02
【问题描述】:

代码请见:http://codepaste.net/djw3cw

如果异步编程的 async/await 真的很快就会像 Linq 一样,我认为这个问题是 Async/Await with a WinForms ProgressBar 的重要扩展

我会很高兴用指针或文字代替代码回答,尽管代码是最佳的。

问题是:如何设置进度条以使用 asynch/await 工作。过去我曾成功使用过 Dispatcher。

Please see: http://codepaste.net/djw3cw  for the code
What is done: a textbox has any text in it converted to an int, then when
"mybutton1" is clicked, work is done based on the int, for int ms (int = 
milliseconds).
During this time, a progressbar "myProgressBar" is shown for 
every tenth-percent step
When work is complete, the label/textblock controls are updated
But the below does not work right: the form simply freezes until the work is
complete.  How to fix it?
How to do this using Task-based Asynchronous Pattern (TAP) or Async/Await,
rather than a Dispatcher?

这是有问题的代码的 sn-p,不言自明。

 private void mybutton1_Click(object sender, RoutedEventArgs e)
    {
        myLabel.Content = myTextBox.Text;

        string myString = myTextBox.Text;

        bool result = Int32.TryParse(myString, out myInteger);

        if (result == true)
        {
        myTextblock.Text = "Success, thread will be delayed by: " +  myInteger.ToString() + " ms";

            //
            int CounterInteger = 0;
            for (int j = 0; j < myInteger; j++) // set # itt
            {

                Thread.Sleep(1); //do some work here

               // myClassDoWork1.Delay_DoWork(myInteger); //optional way to do work in another class...

                if (j % (myInteger / 10) == 0)  //display progress bar in 10% increments
                {

                    CounterInteger = CounterInteger + 10;
                     myProgressBar.Value = (double)CounterInteger; // won't work here in a parallel manner...must use Dispatcher.BeginInvoke Action 
                    //how to make this work using Async/Await?  see: https://stackoverflow.com/questions/17972268/async-await-with-a-winforms-progressbar

                }

            }
            ///
            /// // above does not work properly:  the form simply freezes until the work is complete.  How to fix it?
            ///


            myLabel.Content = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds";
            myTextblock.Text = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds";
            return;
        }
        else
        {
            myTextblock.Text = "Error, integer not entered, try again." + myTextBox.Text;
            myLabel.Content = "Error, integer not entered, try again.";
            return;
        }


    }

【问题讨论】:

  • 请将代码编辑到您的问题中 - 理想情况下编辑得尽可能短,同时仍然完整并展示问题。
  • 嗨,乔恩——我实际上正在阅读你关于“C# 深度学习”这一主题的书。您在 CodePaste 上看到代码了吗?我发现这里剪切和粘贴代码对我来说不是很好,抱歉。
  • 是的,我可以在 CodePaste 上看到代码 - 但它根本不是提问的好方法。熟悉 Stack Overflow 降价编辑器(和预览窗口)是值得的 - 清晰地格式化您的问题(而不仅仅是链接到场外代码)对于创建一个好问题很重要。
  • 好的,让我再试一次...

标签: c# asynchronous progress-bar async-await


【解决方案1】:

您的代码中没有任何 asyncawait。您的 UI 线程阻塞的原因是您在其上运行同步代码。

如果您想要将 CPU 绑定代码推送到后台线程,请使用 Task.Run。然后你可以从 UI 线程await 那个代码。

private async void mybutton1_Click(object sender, RoutedEventArgs e)
{
  myLabel.Content = myTextBox.Text;
  string myString = myTextBox.Text;
  bool result = Int32.TryParse(myString, out myInteger);

  if (result == true)
  {
    myTextblock.Text = "Success, thread will be delayed by: " +  myInteger.ToString() + " ms";
    IProgress<int> progress = new Progress<int>(value => { myProgressBar.Value = value; });
    await Task.Run(() =>
    {
      int CounterInteger = 0;
      for (int j = 0; j < myInteger; j++)
      {
        Thread.Sleep(1);
        if (j % (myInteger / 10) == 0)
        {
          CounterInteger = CounterInteger + 10;
          progress.Report(CounterInteger);
        }
      }
    }

    myLabel.Content = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds";
    myTextblock.Text = "done, delayed work done successfully: in " + myInteger.ToString() + " milliseconds";
    return;
  }
  else
  {
    myTextblock.Text = "Error, integer not entered, try again." + myTextBox.Text;
    myLabel.Content = "Error, integer not entered, try again.";
    return;
  }
}

【讨论】:

  • 感谢您的回答。不幸的是,我刚刚意识到我没有使用 .NET Framework 4.0 而不是 4.5,所以这些功能没有出现在 IntelliSense 中。
  • 在这种情况下,您可以安装Microsoft.Bcl.Async 并使用TaskEx.Run 而不是Task.Run
猜你喜欢
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多