尝试从另一个线程访问复杂对象时发生InvalidOperationException [英] InvalidOperationException when trying to access a complex object from another thread

查看:96
本文介绍了尝试从另一个线程访问复杂对象时发生InvalidOperationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试了很多解决方案之后,我无法以任何方式解决此问题,因此我开始相信对于该问题没有解决方案.

After I tried lots and lots of solutions I couldn't solve this problem by any means so I started to believe that there is no solution for this problem.

我有一个包含复杂属性的对象.例如:List<SomeComplexObject>.我正在工作线程上从此类运行方法,以保持GUI运行,直到工作线程完成.完成执行后,我想使用这些对象的属性来更新GUI,假设我想使用List<SomeComplexObject>遍历此列表并更新GUI.但是每次我尝试访问此列表时,调试器都会抛出InvalidOperationException:调用线程无法访问该对象,因为另一个线程拥有该对象.

I have an object that contains complex attributes. E.g: List<SomeComplexObject>. I am running a method from this class on a worker thread to keep the GUI running until the worker thread finishes. When it finishes execution, I want to use the attributes of these objects to update GUI let's say I want to use List<SomeComplexObject> looping through this list and update the GUI. But each time I try to access this list the debugger throws an InvalidOperationException: The calling thread cannot access this object because a different thread owns it.

我试图使此类的所有属性易变,但不希望我也使用Lazy<T>类方法来解决,但是会出现相同的问题.

I tried to make all attributes of this class volatile but with no hope I also used Lazy<T> class approach to solve but the same problem occurs.

包含worker函数的类:

Class that contain the worker function:

public class MainModules
{

    #region Attributes

    public VIDEO video; 

    public string VideoPath
    {
        get;
        set;
    }

    LowLevelModule lowLevelOutput;

    //this list that I want to use to Update GUI 
    public volatile List<FaceRecognitionModule> faceModuleOutput;

    //worker function running on different thread
     public void RunMainModules()
     {
        //some complex work to set the class attributes
     }
 }

在GUI类中创建线程

 private void RunMainModules_BtnClick(object sender, RoutedEventArgs e)
    {
      //  MainModule = new MainModules(mainModuleObj, Inpath, lif, keyframefolderpath, trdbpath, labelspath, rrankspath, alignmatpath, 11, 10);
        this.LazyMainModule = new Lazy<MainModules>(this.InitLazyMainModule);
        MainModuleThread = new Thread(this.RunMainModules);
        MainModuleThread.Start(MainModule);

    }

    public MainModules InitLazyMainModule()
    {
        return new MainModules(mainModuleObj, Inpath, lif, keyframefolderpath, trdbpath, labelspath, rrankspath, alignmatpath, 11, 10);
    }
     public void RunMainModules(Object obj)
    {
        //MainModules mm = obj as MainModules;
        MainModules mm = LazyMainModule.Value;
        mm.RunMainModules();
        this.Dispatcher.Invoke((Action)(() =>
        {
            this.InitSpeechRec_Btn.IsEnabled = true;
        }));
    }

当我尝试从GUI访问类MainModules中的faceModuleOutput时,我得到了InvalidOperationException.

When I try to access faceModuleOutput in class MainModules from GUI I got InvalidOperationException.

Image img = new Image();
//InvalidOperationException occurs here
img.Source = LazyMainModule.Value.faceModuleOutput[0].keyframes[1].keyframe;

要简要介绍此帖子: 我想从主线程访问由后台线程实例化的对象,但是它抛出

To brief this post: I want to access an object instantiated by a background thread from main thread but it throws

InvalidOperationException : The calling thread cannot access this object because a different thread owns it. 

推荐答案

最后,我找到了解决方案...类BitmapImage是线程仿射的,因此无法被多个线程访问,您需要首先打开它只能读取封闭状态以进行写入,因此编译器可以保证没有线程会修改其内容

Finally I found the solution ... Class BitmapImage is thread-affine so it can't be accessed by multiple threads you need first to make it opened for reading only closed for writing so the compiler can guarantee that no threads will modify it's content

所以解决方案...:

 //keyframe here is a BitmapImage so on creation we must call keyframe.Freeze()
 LazyMainModule.Value.faceModuleOutput[0].keyframes[1].keyframe;

KeyFrame:

public class KeyFrame
{
    public volatile BitmapImage keyframe;
    public volatile List<string> personsNames;
    public volatile List<string> categories;

    public KeyFrame(BitmapImage keyframe, List<string> personsNames, List<string> categories)
    {
        this.keyframe = keyframe;
        //here we call Freeze funcition on creation to make it modifiable 
        this.keyframe.Freeze();
        this.personsNames = personsNames;
        this.categories = categories;
    }
}

这篇关于尝试从另一个线程访问复杂对象时发生InvalidOperationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆