繁体   English   中英

WPF 中的调度程序和异步等待

[英]Dispatcher and async await in WPF

我正在尝试在 WPF/C# 中学习异步编程,但我一直坚持异步编程和使用 Dispatchers。 它们是不同的还是它们或将在同一场景中使用? 我愿意保持这个问题简短,以免含糊不清,因为我知道我在 WPF 中混淆了一个概念和一个函数,但还不足以在功能上正确使用它。

我在这里问了一个问题后出现了我的疑问, 这是我的问题,有人告诉我使用Dispatcher解决这个问题,WPF 在单线程上运行,你需要使用BeginInvoke ,这是我第一次听到Dispatcher ,在此之前我只是用户 async 并等待Task.Run仅使用这 3 个关键字。

但是这篇文章是使用 WPF 在 C# 中进行异步编程

我需要做的就是将几页加载到Grid ,这发生在应用程序的开始(我认为这部分处理Dispatcher因为它是 UI 的一部分),然后 CRUD 到数据库。

你不应该使用Dispatcher 相反,您可以使用awaitIProgress<T>将工作委托回 UI 线程。

例如:

private async void b1_Click(object sender, RoutedEventArgs e)
{
  // We are starting on the UI thread here.
  txtb1.Text = "";
  var watch = System.Diagnostics.Stopwatch.StartNew();

  await writeintxtbx();

  // After the await completes, we return to the UI thread because await captured the UI context.

  watch.Stop();
  var elapsedtm = watch.ElapsedMilliseconds;

  // Since we're on the UI thread, we can update UI elements.
  txtb1.Text += $"TOTAL TIME {elapsedtm} \n\n\n";
}

如果您需要使用进度更新来更新 UI 元素,请使用IProgress<T>

private async Task writeintxtbx()
{
  var progress = new Progress<string>(x => txtb1.Text += x);
  await Task.Run(() => Task1(progress));
  await Task.Run(() => Task2(progress));
}

private void Task1(IProgress<string> progress)
{
  progress?.Report($"Task 01 Done \n\n");
}

private void Task2() 
{
  progress?.Report($"Task 2 done \n\n");
}

我会笼统地解释,而不是完全解释。

当你想异步执行一个方法时,你创建了一个任务。 该任务由线程池中的任意线程执行。

但是,如果您需要使该方法在特定线程中执行怎么办?
这是 UI 元素的常见任务 - 它们应该始终只在应用程序的主线程上运行。

为了解决这个问题,创建了线程调度程序。
每个线程只能有一个调度程序。
它是在您第一次访问时创建的。
使用线程调度器,您可以在该线程上执行异步方法。

Invoke - 在 Dispatcher 线程上同步执行一个方法。
这就像调用一个常规的同步方法。
在执行传递给 Invoke 的方法之前,不会继续执行 main 方法(在其中调用 Invoke)。
执行 main 方法的线程也会停止。
极少使用的调用。

InvokeAsync 和 BeginInvoke 是异步执行。
他们在小细节上有所不同——我现在不会去解释他们。
这些方法返回一个 DispatcherOperation 对象。
您可以使用它与执行您的方法的任务进行交互。
最常见的用途是 BeginInvoke 而不接收 DispatcherOperation。

加载数据的最佳方式是使用异步方法(async-await)创建模型。 加载数据后,ViewModel 将接收此数据并在其属性中提供它。 当 ViewModel 属性更改其值时,您需要引发 PropertyChanged 事件(ViewModel 必须实现 INotifyPropertyChanged)。 在什么流中会发生这种情况 - 没关系。

UI 元素(WPF 视图)将通过 ViewModel 属性的绑定接收此数据。 绑定机制的设计方式是,无论属性在哪个线程中发生更改,绑定都将始终在其 Dispatcher 中更新 UI 元素。

通过这样的实现,您无需担心从数据库接收数据的流或其他处理数据的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM