0

i'm stucked at some point which seemed to be easy....

I have a View with an image control:

 <Image x:Name="ImageControl" Source="{Binding DisplayedImage, UpdateSourceTrigger=PropertyChanged }" HorizontalAlignment="Left" 
    Margin="0,0,0,0" Stretch="Fill" VerticalAlignment="Bottom" 
     Width="800" Height="300" Grid.Column="3" Grid.Row="3" />

And creating the Datacontext in the background :

public MainWindow()
        {
            InitializeComponent();
            MainViewModel VM = new MainViewModel();
            
            ImageControl.DataContext = VM;
        }

In my Viewmodel i have the property as well as doing something on the backgroundworker. In the backgroundworker i raise an event and the event handler should update the property which should result in an update of the image:

public event EventHandler<NewImageToShowEventArgs> NewImageToShowEvent;

        public class NewImageToShowEventArgs : EventArgs
        {
            public BitmapSource NewImage { get; set; }
            public Bitmap NewImage2 { get; set; }

        }

 public MainViewModel()
        {
            uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            int Result = GetCamera();
            //MessageBox.Show(Convert.ToString( Result));
            // Assign Each Task with GrabImage helper
            
            Grabbgw.DoWork += DoGrab;
           // Grabbgw.RunWorkerCompleted += GrabWorkerCompleted;
            bgws.Add(Grabbgw);
            

            //assign Events
            NewImageToShowEvent += NewImageToShow;
            StartGrab();
        }
 private void NewImageToShow(object sender, NewImageToShowEventArgs e)
        {
            try
            {
                Application.Current.Dispatcher.Invoke((new Action(() =>
                {
                    //DisplayedImage.Freeze(); // through a different error
                    DisplayedImage = e.NewImage.Clone();
                   // DisplayedImage2 = e.NewImage2;
                })));
                //Task.Factory.StartNew(() => DisplayedImage2 = e.NewImage2, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
                //App.Current.MainWindow.Dispatcher.BeginInvoke(new Action(() =>
                //{

                //    DisplayedImage = e.NewImage.Clone();
                //    DisplayedImage2 = e.NewImage2;
                //}));
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }

        }
 NewImageToShowEventArgs  args = new NewImageToShowEventArgs();
                            args.NewImage = rawImage.bitmapsource.Clone() ;
                            args.NewImage2 = rawImage.bitmap;
                            NewImageToShowEvent?.Invoke(this, args);

I tried several things but all results in: "The calling thread cannot access this object because a different thread owns it." I searched now for hours without any results. I mean i tried the suggestions but they doesn't solved the problem. General Info: I get the image from a camera as either Bitmap or BitmapSource.

In the Output window it shows additional errors:

Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll

I hope somebody has an idea why i still get the error.

Thanks!

All the best, Jan

Eggord
  • 13
  • 5
  • Not sure what exactly this code is doing, but if you create a BitmapImage in a thread other than the UI thread, you have to `Freeze()` it before passing it to the UI thread, where you assign it to the Source property of an Image element, e.g. as shown here: https://stackoverflow.com/a/31769850/1136211 or here: https://stackoverflow.com/a/16075200/1136211 – Clemens Jul 20 '21 at 12:40
  • @Clemens : there was a small mistake in my code i actually don't set the source of the image in code(but in xaml). If i do "DisplayedImage.Freeze();" in the event handler, i get the follow error: "Object reference not set to an instance of an object." – Eggord Jul 20 '21 at 13:01
  • But you have no clue why DisplayedImage is null? Where in your question is that Freeze call? – Clemens Jul 20 '21 at 13:04
  • No i don't have any idea why it is null. Is it null? I thought it is thread error. it is not in the code since it troughs a different error but i tried it out. I will edit the post above and add the freeze as comment – Eggord Jul 20 '21 at 13:08
  • You are calling `DisplayedImage.Freeze()` before assigning a value to DisplayedImage. Think about it. It's perhaps the perfect time to start using the debugger. – Clemens Jul 20 '21 at 13:14
  • Why is the questions closed? the other question is not an answer to my question! I tried freeze and it doesn't helped plus the other question is about BitmapImage not BitmapSource – Eggord Jul 20 '21 at 13:16
  • It is. Just make sure the Freeze call has a chance to succeed. The explanation about thread affinity and Freezable given in the answer to the duplicate question applies to BitmapSource as well as to BitmapImage. BitmapImage is just a derived BitmapSource. – Clemens Jul 20 '21 at 13:17
  • Ok true i should have checked the BitmapImage. So the error happens while assigning a value to displayImage so i cannot only freeze before! Unless there is a general problem which i'm not aware of. – Eggord Jul 20 '21 at 13:48
  • You should assign a frozen BitmapSource to DisplayedImage. Perhaps like `var bitmap = e.NewImage; bitmap.Freeze(); DisplayedImage = bitmap;` where I have omitted the `.Clone()` call on NewImage because it is unclear whether that is really necessary. – Clemens Jul 20 '21 at 13:56
  • Amazing that worked (partially). But i don't know why. I would not come up with this: I thought it Bitmap is a reference type so bitmap and e.Newimage has the same pointer. So e.NewImage.Freeze() is the same. Anyway i don't have to understand everything. But feel free to give me some hints. – Eggord Jul 22 '21 at 11:16
  • Ah and now i get memoryleaks...when i search for solution: a freeze() should help...lol that is what i just added and caused the memoryleak :( – Eggord Jul 22 '21 at 11:18
  • Just in case it is still unclear, you were calling `DisplayedImage.Freeze()` before you ever assigned a value to the `DisplayedImage` property. It was therefore `null` and you got a `NullReferenceException`. Besides that, you have to call `Freeze()` before you make that assignment. `e.NewImage.Freeze(); DisplayedImage = e.NewImage;` is totally equivalent. – Clemens Jul 22 '21 at 11:35
  • Ah ok understand. Thanks! So i was not totally wrong just the problem with null. Do you have any hint for the memory leak? – Eggord Jul 22 '21 at 11:47
  • Ok last Comment here!: The memory leak originated from the camera dll not from the image control. – Eggord Jul 22 '21 at 13:56

0 Answers0