InvalidOperationException when trying to access a complex object from another thread

After I tried many and many solutions, I could not solve this problem, so I began to think that there was no solution to this problem. I have an Object that contains complex attributes, for example: List. I run a function from this class in a workflow to support the GUI until the workflow completes, when the workflow completes execution. I want to use the attributes of these objects to update the GUI, lets say that I want to use the List loop through this list and update the GUI, but every time I try to access this list, the debugger throws an InvalidOperationException: the calling thread cannot access this object because it owns another thread. I tried to make all the attributes of this class unstable,but without hope, I also used the Lazy class approach to solve, but the same problem arises

which contains a working 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
     }
 }

Creating a theme in a GUI class

 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;
        }));
    }

when i try to access faceModuleOutputin class MainModulesfrom GUI i got InvalidOperationException

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

To comment on this post: I want to access an object created by a background thread from the main thread, but it throws

InvalidOperationException : The calling thread cannot access this object because a different thread owns it. 
+2
source share
3 answers

Finally, I found a solution ... The class BitmapImageis an affine thread, so it cannot be accessed by several threads that you need, first of all, so that it is open for reading, only closed for writing, so the compiler can guarantee that none stream will change its contents

So the solution ...:

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

class 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;
    }
}
0

/ GUI. .

, MainModuleThread ( ) Image. GUI (, RunMainModules_BtnClick)

0

, . /, , . , , , .

UIObject.Dispatcher.Invoke(() => {
   //[Perform your action in here]
  });
0
source

Source: https://habr.com/ru/post/1523618/


All Articles