我有一个 .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/