线程问题;调用线程无法访问该对象,因为它被另一个线程拥有.任何解决方案

本文关键字:线程 因为 另一个 解决方案 任何 拥有 对象 问题 调用 访问 | 更新日期: 2023-09-27 18:10:34

我有一个包含文件名的listview。我有另一个listview,其中包含重命名这些文件的可能操作。最后,我有一个显示结果预览的标签。当一个对象在每个列表中被选中时,我想显示预览。您只能选择一个文件,但可以选择一个或多个操作。我使用WPF/Xaml作为我的UI。我选择用线程来执行预览。

这是我的一部分代码:

    private Thread _thread;
    public MainWindow()
    {
        InitializeComponent();
        _thread = new Thread(DoWork);
    }
    public void DoWork()
    {
        while (true)
        {
            FileData fileData = listViewFiles.SelectedItem as FileData; // ERROR HERE
            if (fileData != null)
            {
                string name = fileData.FileName;
                foreach (var action in _actionCollection)
                {
                    name = action.Rename(name);
                }
                previewLabel.Content = name;
            }
            Thread.Sleep(1000);
        }
    }
    private void listViewFiles_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        _thread.Start();
    }

在运行时,我得到错误"调用线程不能访问这个对象,因为一个不同的线程拥有它。"在FileData FileData = listViewFiles。SelectedItem作为FileData;线。你知道我该怎么做吗?

线程问题;调用线程无法访问该对象,因为它被另一个线程拥有.任何解决方案

你不能从非UI线程修改或访问UI。因此,如果你仍然想使用不同的线程,你需要做的第一件事是添加某种模型(有关绑定和模型的更多信息,请尝试搜索"wpf mvvm"),然后将你的listViewFiles.SelectedItem绑定到这个模型的一些属性,这将允许你跨线程访问SelectedValue。其次,你需要将所有改变UI的逻辑分离为方法或使用lambda,所以最后它看起来像这样:

public void DoWork() 
{ 
    while (true) 
    { 
        FileData fileData = Model.SelectedValue;
        if (fileData != null) 
        { 
            string name = fileData.FileName; 
            foreach (var action in _actionCollection) 
            { 
                name = action.Rename(name); 
            } 
            this.Dispatcher.Invoke((Action)()=>  //use Window.Dispatcher
            {
              label3.Content = fileData.FileName; 
              label4.Content = name;
            }); 
        } 
        Thread.Sleep(1000); 
    } 
} 

乌利希期刊指南。关于与UI同步的一些附加说明:在WPF中,每个UI对象都继承自DispatcherObject类。因此,对该类型对象的所有访问只能从创建该对象的线程中进行,如果你想从另一个线程访问DispatcherObject(DO),你需要使用DO.Dispatcher.Invoke(Delegate)方法,这将使你的代码排队到DO线程。综上所述,要在UI线程中运行代码,你需要使用任何UI元素的Dispatcher,在这种情况下,我们使用窗口的Dispatcher(假设代码在窗口代码后面)。

简单的回答是你不能这样做:线程A不能直接访问线程B创建的winforms对象(控件)

在实践中,你可以使用委托来安全地在另一个线程上运行:

form.Invoke(new MethodInvoker(() => {
       FileData fileData = listViewFiles.SelectedItem as FileData; // ERROR HERE
        if (fileData != null)
        {
            string name = fileData.FileName;
            foreach (var action in _actionCollection)
            {
                name = action.Rename(name);
            }
            previewLabel.Content = name;
        }
   }));

然而,你可能只是想使用后台worker: http://msdn.microsoft.com/en-us/library/8xs8549b.aspx

详情见:http://weblogs.asp.net/justin_rogers/pages/126345.aspx

相关文章: