异步进度条更新 [英] Async Progress Bar Update

查看:110
本文介绍了异步进度条更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用async await来基于复制操作更新WinForm上的进度条,但是进度条仅在Copy函数完成后才会更新,然后引发异常,它可以不会更新,因为它不在同一线程上?

I am trying to use an async await to update a progress bar on my WinForm based on a copy operation, but the progress bar will only update when the Copy function has finished, and then throws an exception that it can't update as it's not on the same thread?

复制"功能不需要与UI进行交互,但是进度"功能需要进行交互.

The Copy function doesn't need to interact with the UI but the Progress function does.

虽然UI并未被阻止,所以它看起来异步部分正在按预期工作,它只是在与UI线程交互而没有.

The UI isn't blocked though, so it would appear the async part is working as expected, it's just interacting with the UI thread that isn't.

long fileProgress = 0;
long totalProgress = 0;
bool complete = false;

CopyFileEx.CopyFileCallbackAction callback(FileInfo source, FileInfo destination, object state, long totalFileSize, long totalBytesTransferred)
{
      fileProgress = totalBytesTransferred;
      totalProgress = totalFileSize;
      return CopyFileEx.CopyFileCallbackAction.Continue;
}

async Task Progress()
{
      await Task.Run(() =>
      {
           while (!complete)
           {
                if (fileProgress != 0 && totalProgress != 0)
                {
                     fileProgressBar.Value = (int)(fileProgress / totalProgress) * 100;
                }
           }
      });
}

private async void startButton_Click(object sender, EventArgs e)
{
      Copy();
      await Progress();
      MessageBox.Show("Done");
}

void Copy()
{
      Task.Run(() =>
      {
           CopyFileEx.FileRoutines.CopyFile(new FileInfo(@"C:\_USB\Fear.rar"), new FileInfo(@"H:\Fear.rar"), CopyFileEx.CopyFileOptions.All, callback, null);
           complete = true;
      });
}

推荐答案

  1. async / await的全部目的是在处理I/O时不阻塞线程-任何线程.将阻塞 I/O调用放入Task.Run()内(就像您在Copy()中所做的那样)并不能避免阻塞-它只是创建一个Task,稍后其他线程将接听该Task,以查找当它碰到阻塞CopyFileEx.FileRoutines.CopyFile()方法时,它本身就被阻塞了.
  2. 由于未正确使用async / await(无论上述内容如何),因此出现此错误.考虑一下哪个线程正在尝试修改UI对象fileProgressBar:拾取您在Task.Run()上创建的Task的随机线程池线程将执行fileProgressBar.Value = ...,这显然会抛出.
  1. async / await is all about not blocking a thread - any thread - when dealing with I/O. Putting a blocking I/O call inside Task.Run() (like you did in Copy()) doesn't avoid blocking - it just create a Task which some other thread will later pick up, just to find it itself gets blocked when it hits the blocking CopyFileEx.FileRoutines.CopyFile() method.
  2. You are getting that error because you are not using async / await properly (regardless the above). Think about which thread is trying to modify the UI object fileProgressBar: the random threadpool thread that picks up the Task you create on Task.Run() gets to execute fileProgressBar.Value = ..., which will obviously throw.

这是避免这种情况的一种方法:

This is one way to avoid this situation:

async Task Progress()
{
      await Task.Run(() =>
      {
           //A random threadpool thread executes the following:
           while (!complete)
           {
                if (fileProgress != 0 && totalProgress != 0)
                { 
                    //Here you signal the UI thread to execute the action:
                    fileProgressBar.Invoke(new Action(() => 
                    { 
                        //This is done by the UI thread:
                        fileProgressBar.Value = (int)(fileProgress / totalProgress) * 100 
                    }));
                }
           }
      });
}

private async void startButton_Click(object sender, EventArgs e)
{
      await Copy();
      await Progress();
      MessageBox.Show("Done");  //here we're on the UI thread.
}

async Task Copy()
{
    //You need find an async API for file copy, and System.IO has a lot to offer.
    //Also, there is no reason to create a Task for MyAsyncFileCopyMethod - the UI
    // will not wait (blocked) for the operation to complete if you use await:
    await MyAsyncFileCopyMethod();
    complete = true;
}

这篇关于异步进度条更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆