c# - 使用 TPL 任务更新 UI 不会立即更新 UI

标签 c# winforms task-parallel-library

我有一个 .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 更新。

最佳答案

在 UpdateProgressCount 中,您可能想要调用带有进度的表单。这是更新事物的标准方式,而不是通过创建另一个任务。

此外,我相信通过等待在 UI 线程上运行的任务,您的后台线程将继续运行。但我可能对那部分不正确。无论如何,如果您使用应解决问题的进度调用表单。

关于c# - 使用 TPL 任务更新 UI 不会立即更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12389859/

相关文章:

c# - Visual Studio "inconsistent line endings"

c# - 如何在 WPF TextBox 中模拟粘贴?

c# - 将列表绑定(bind)到 gridview C#

c# - 如何将 .net 4.5 Async/Await 示例转换回 4.0

c# - Objective-C <-> 单桥

c# - 打开xml sdk 2.0用公式读取excel单元格值

c# - 防止下拉区域在 Windows 窗体中打开组合框控件

c# - 我在哪里可以获得 "open hand"/"closed hand"鼠标光标?

c - 使用 TPL 在结构中序列化 wchar_t*

c# - 将同步代码包装到异步方法中的最佳方法是什么