我有一个 .NET Windows 窗体,它创建了一个异步运行的任务。该任务应调用以更新其进度的 UI。它可以工作,但进度条只会随着某种延迟而更新。
public partial class WaitDialog : Form
{
private readonly TaskScheduler _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private void ReportViewerWaitForm_Load(object sender, EventArgs e)
{
_asyncTask = Task.Factory.StartNew(Calculate(), _cancellationTokenSource.Token);
_asyncTask.ContinueWith(task => Close(), CancellationToken.None, TaskContinuationOptions.None, _uiScheduler);
}
private void Calculate()
{
UpdateProgressCount(0, 1000);
for (int i = 0; i < 1000; i++)
{
// do some heavy work here
UpdateProgressCount(i);
}
}
private void UpdateUserInterface(Action action)
{
Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, _uiScheduler).Wait();
}
public void UpdateProgressCount(int count)
{
UpdateUserInterface(() => progressBar.Value = count);
}
public void UpdateProgressCount(int count, int total)
{
UpdateUserInterface(() =>
{
progressBar.Minimum = 0;
progressBar.Maximum = total;
});
UpdateProgressCount(count);
}
private void WaitForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!_asyncTask.IsCompleted)
{
e.Cancel = true;
}
}
}
进度条设置正确,当表单关闭时,它的值设置为 1000(或 100%),但它不会在 UI 上以这种方式显示,它只显示大约 50% 的完成。
启动更新 UI 的任务,然后调用 Wait(),但异步任务似乎在更新 UI 之前继续运行。我认为这是因为 UI 线程本身做了某种 BeginInvoke() 来更新 UI。
最终,当异步(繁重的工作)任务完成时,UI 并未完全更新并且表单关闭。但是 UI 任务 Wait()、Application.DoEvents() 或 progressBar.Update() 有任何作用,以允许 UI 在返回繁重的工作任务之前进行更新。