backgroundworker和不同的线程

时间:2016-03-04 19:31:47

标签: c# wpf int backgroundworker

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

1 个答案:

答案 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();
    }

}