c# - C# 在异步/等待代码中实现调度程序
问题描述
我有一个 wpf 应用程序,其中一个功能是复制文件。它可以正常运行,但有时会冻结 UI,因此我正在尝试向其添加异步/等待功能。
这是代码:
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string[] files = filePickedTextBox.Text.Split('\n');
await Task.Run(() =>
{
foreach (var file in files)
{
try
{
AddValueLoadingBar(20, true);
File.Copy(file, Path.Combine(dialog.SelectedPath, Path.GetFileName(file)));
newDirTextBox.Text = Path.Combine(dialog.SelectedPath, Path.GetFileName(file));
}
catch(Exception ex)
{
newDirTextBox.Text = ex.ToString();
}
finally
{
AddValueLoadingBar(100, true);
}
}
});
我曾尝试在多个位置添加 dispatcher.invoke,但当它需要与文本框对话时,总是会收到一个错误,即它要求来自不同线程的请求。
我已经在这工作了几个小时,并且在网上搜索了许多 stackoverflow 线程和其他文档,但我不知道如何实现这一点。
我也知道我的进度条实现很糟糕..但我现在并不担心,因为我一开始就无法让它运行而不冻结。
任何帮助都会很棒。
谢谢
解决方案
这是您使用System.Windows.Threading.Dispatcher类的地方。
您知道对话框构造函数将在主线程上运行。因此,当创建对话框时,您将主线程的调度程序记录为成员变量。
然后,在 Task 线程中,确保您通过此调度程序将任何更新更改发送到 Windows 线程。
using System.Windows;
class MyTestDialog
{
readonly Dispatcher _uiThreadDispatcher = Dispatcher.CurrentDispatcher;
public async Task DoSomethingInBackround()
{
await Task.Run(
() =>
{
//
// Do a bunch of stuff here
//
_uiThreadDispatcher.BeginInvoke(
new Action(
() => newDirTextBox.Text = "Some progress text";
)
);
//
// Do some more stuff
//
}
);
}
}
推荐阅读
- android - 片段仅显示在右上角
- sql - oracle 11g 替代先获取?
- python - 必须使用带 VPN 的 Selenium
- javascript - jQuery - 事件目标多个 id 选择器?
- pascal - 旋转图像的简单方法
- java - 带有参数的子类的构造函数?
- android - Android Firebase:覆盖值而不是创建新条目
- r - R:如何真正从 S4 对象中删除 S4 插槽(附上解决方案!)
- css - Flexbox 和 CSS 位置
- reactjs - Material-UI TreeView - 如何获取被点击的 TreeItem 的 nodeId?