C
C#2y ago
Max

❔ c# access variable from other thread

I've been searching the web for a while and I cant seem to access a variable like this: img.Source = image; where image comes from a different thread (Task.Run(...)). I have tried img.Dispatcher.Invoke(() => img.Source = image); and
Dispatcher.BeginInvoke(() =>
{
img.Source = image;
});
Dispatcher.BeginInvoke(() =>
{
img.Source = image;
});
but both do not work. Error: System.InvalidOperationException: "The calling thread cannot access this object because a different thread owns it." Full code:
BitmapImage[] BitmapImages = await Task.Run(() =>
{
BitmapImage[] bitmapImages = new BitmapImage[files.Count];
int i = 0;
foreach (string file in files)
{
BitmapImage image = new();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.DecodePixelWidth = 200;
image.UriSource = new Uri(file);
image.EndInit();

bitmapImages[i++] = image;
}

return bitmapImages;
});

foreach (BitmapImage image in images)
{
if (image == null)
return;

Image img = new();
img.Source = image;

}

return ;
BitmapImage[] BitmapImages = await Task.Run(() =>
{
BitmapImage[] bitmapImages = new BitmapImage[files.Count];
int i = 0;
foreach (string file in files)
{
BitmapImage image = new();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.DecodePixelWidth = 200;
image.UriSource = new Uri(file);
image.EndInit();

bitmapImages[i++] = image;
}

return bitmapImages;
});

foreach (BitmapImage image in images)
{
if (image == null)
return;

Image img = new();
img.Source = image;

}

return ;
8 Replies
Pacyfist
Pacyfist2y ago
I assume this is WPF. This code runs in code behind file, or in viewmodel? Because if it's the ViewModel then this like creates the img in a different thread, and could be the source of your problem. Image img = new();
foreach (BitmapImage image in images)
{
if (image == null)
return;

Dispatcher.BeginInvoke(() =>
{
Image img = new();
img.Source = image;
});
}
foreach (BitmapImage image in images)
{
if (image == null)
return;

Dispatcher.BeginInvoke(() =>
{
Image img = new();
img.Source = image;
});
}
JakenVeina
JakenVeina2y ago
yes, WPF, along with basically every GUI library, is single-threaded any work that you're doing that affects GUI objects needs to be done on the main UI thread if you're marshalling stuff OFF of the main UI thread (E.G. with Task.Run()) then you have to marshall it back (E.G. with Dispatcher.Invoke() or await)
TheBoxyBear
TheBoxyBear2y ago
Did you correct your full code with the suggestions? What is written now should work, generating objects in a task and returning the result, capturing it in the original thread with await
Max
MaxOP2y ago
I will follow the suggestions shortly. I am on eu, kinda late when i posted and early now
TheBoxyBear
TheBoxyBear2y ago
So yeah unless there's a specific oddity with the Image and Bitmap classes I don't know about, it should work But such oddities would have to be tied to something inside the objects, not the Bitmap références themselves like the error says
Max
MaxOP2y ago
But how do I get access to Image img outside of Dispatcher.BeginInvoke? this is kinda of my main problem since a few days I want to async load in pictures and then present them as previews before loading in the pictures in full res
TheBoxyBear
TheBoxyBear2y ago
No need for invoking if you await
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server