后台工作者和不同的线程

本文关键字:线程 工作者 后台 | 更新日期: 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();
    }

}