我有一个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
的信息并递归地查找文件夹可以包含的文件数。
感谢将来的回答。
编辑:此处包含完整评论的代码 - &gt; http://codepaste.net/r1qejd
答案 0 :(得分:0)
几乎每个WPF元素都具有线程关联性。这意味着只应从创建该元素的线程访问此类元素。为此,需要线程关联的每个元素最终都来自DispatcherObject
类。此类提供名为Dispatcher
的属性,该属性返回与WPF元素关联的Dispatcher
对象。
Dispatcher
类用于对其附加线程执行工作。它有一个工作项队列,负责在调度程序线程上执行工作项。
You can find on the following link some more details on the subject.
正如MSDN所说:
只有一个线程可以修改UI线程。但是如何做背景 线程与用户交互?后台线程可以询问UI 线程以代表它执行操作。它通过这样做 使用UI线程的Dispatcher注册工作项。该 Dispatcher类提供了两种注册工作项的方法: Invoke和BeginInvoke。两种方法都为一个委托安排 执行。 Invoke是一个同步调用 - 也就是说,它不会返回 直到UI线程实际完成执行委托。 BeginInvoke是异步的并立即返回。
因此请尝试使用Dispatcher
。例如:
int CountFileToCheck;
textBox_UpdatedBuildPath.Dispatcher.Invoke(() => {
CountFileToCheck=Directory.GetFiles(textBox_UpdatedBuildPath.Text, "*", SearchOption.AllDirectories).Length;
});
<强>更新强>
我为你制作了一个样本并进行了测试。它运作得很好。
<强> 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();
}
}