后台工作者和不同的线程
本文关键字:线程 工作者 后台 | 更新日期: 2023-09-27 18:37:22
我有一个WinForm
的应用程序,想转换为WPF
,在 200 个错误干净后,我正在尝试工作,但总是有一个我无法解决的错误。
在我的BackgroundWorker1_DoWork
,我正在尝试使用以下方法检索目录中有多少个文件:
//Set the progress bar
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render,
new Action(() => {
Directory.GetFiles((textBox_UpdatedBuildPath.Text, "*",
SearchOption.AllDirectories).Length;
})
); //<-----------------HERE
并得到以下错误:
调用线程无法访问此对象,因为不同的 线程拥有它。
快速搜索后,当用户想要更新UI时,它似乎是相关的,但似乎不是我的情况,我需要来自Textbox
的信息并递归查找文件夹可以包含多少个文件。
谢谢未来的答案。
编辑:这里是带有完整注释的代码 -> http://codepaste.net/r1qejd
几乎每个 WPF 元素都有线程相关性。这意味着只能从创建元素的线程访问此类元素。为此,每个需要线程亲和性的元素最终都从类派生DispatcherObject
。此类提供一个名为 Dispatcher
的属性,该属性返回与 WPF 元素关联的Dispatcher
对象。
Dispatcher
类用于在其附加的线程上执行工作。它有一个工作项队列,它负责在调度程序线程上执行工作项。
您可以在以下链接中找到有关该主题的更多详细信息。
正如MSDN所说:
只有一个线程可以修改 UI 线程。但是背景如何 线程与用户交互?后台线程可以询问 UI 线程以代表其执行操作。它通过以下方式做到这一点 向 UI 线程的调度程序注册工作项。这 调度程序类提供了两种用于注册工作项的方法: 调用和开始调用。两种方法都安排委托 执行。调用是一个同步调用 - 也就是说,它不返回 直到 UI 线程实际完成委托的执行。 BeginInvoke 是异步的,并立即返回。
所以尝试使用 Dispatcher
.例如:
int CountFileToCheck;
textBox_UpdatedBuildPath.Dispatcher.Invoke(() => {
CountFileToCheck=Directory.GetFiles(textBox_UpdatedBuildPath.Text, "*", SearchOption.AllDirectories).Length;
});
更新:
我为你做了一个axampre并测试了它。它工作得很好。
XAML:
<StackPanel>
<Button Name="btn" Click="btn_Click" Content="Foo Button"/>
<TextBox Name="textBox" Text="123"/>
</StackPanel>
代码隐藏:
public partial class MainWindow : Window
{
BackgroundWorker bw;
public MainWindow()
{
InitializeComponent();
bw = new BackgroundWorker();
}
private void btn_Click(object sender, RoutedEventArgs e)
{
bw.DoWork += (o, a) =>
{
try
{
string str = "";
textBox.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
str = textBox.Text;
MessageBox.Show(str);
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
//e.Result = LoadXmlDoc();
};
bw.RunWorkerAsync();
}
}