Error: Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher
BitmapImage
is DependencyObject
so it does matter on which thread it has been created because you cannot access DependencyProperty
of an object created on another thread unless it's a Freezable
object and you can Freeze
it.
Makes the current object unmodifiable and sets its IsFrozen property to true.
What you need to do is call Freeze
before you update Image
:
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
as pointed out by @AwkwardCoder here is Freezable Objects Overview
Must create DependencySource on same Thread as DependencyObject
The SolidColorBrush is a Freezable which is a derived DispatcherObject. DispatcherObjects have thread affinity - i.e it can only be used/interacted with on the thread on which it was created. Freezables however do offer the ability to freeze an instance. This will prevent any further changes to the object but it will also release the thread affinity. So you can either change it so that your property is not storing a DependencyObject like SolidColorBrush and instead just store the Color. Or you can freeze the SolidColorBrush that you are creating using the Freeze method.
Must create DependencySource on same Thread as the DependencyObject even by using Dispatcher WPF
When loading a BitmapImage from a Stream, you would usually close the Stream as soon as possible and make sure the BitmapImage is loaded immediately, by setting BitmapCacheOption.OnLoad
.
private static BitmapImage ToBitmapImage(Bitmap bitmap)
{
var start = 420;
var end = 1920 - 2 * 420;
var croppedBitmap = bitmap.Clone(
new System.Drawing.Rectangle(start, 0, end, 1080),
bitmap.PixelFormat);
var bi = new BitmapImage();
using (var ms = new MemoryStream())
{
croppedBitmap.Save(ms, ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms;
bi.EndInit();
}
bi.Freeze();
return bi;
}
Must create DependencySource on same Thread as the DependencyObject when changing SelectedItem
Set the SelectedItem property back on the UI thread once the Task has finished:
public void OnLoad()
{
StartRunning(this, null);
Task.Factory.StartNew(new Action(() =>
{
Load();
})).ContinueWith(task =>
{
SelectedItem = Results[0];
StopRunning(this, null);
}, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}
You can only access a UI element on the thread on which it was originally created so if your UpdatePoints()
method accesses any control you must call this method on the UI thread.
Must create DependencySource on same Thread as the DependencyObject using await/async
You can't generally create a control on one thread and then interact with it one another one, but a frozen freezable can be shared across threads so you can try to freeze the Model3D
before you return it:
private Model3D Load(string path)
{
var model = importer.Load(path);
model.Freeze();
return model;
}
Please refer to MSDN for more information about freezables.
Must create DependencySource on same Thread as the DependencyObject. when binding Background
Whatever code is directly accessing your UI, you can only run on the UI thread.
Use a dispatcher to run it there, e.g.:
Application.Current.Dispatcher.Invoke(() =>
{
// the code that's accessing UI properties
});
Must create DependencySource on same Thread as the DependencyObject When Create GridView
As the error says Dependency Property and its corresponding binding have to be created on same thread
. It can't be set on different threads. Put the creation of grid on UI dispatcher too. Since your ListView View
DP is created on UI thread, hence its source property i.e. GridView
should also be on UI thread.
Application.Current.Dispatcher.Invoke((Action)(delegate
{
GridView grid = new GridView();
grid.Columns.Add((GridViewColumn)myresourcedictionary["gridDirFileName"]);
grid.Columns.Add((GridViewColumn)myresourcedictionary["gridDirFileType"]);
grid.Columns.Add((GridViewColumn)myresourcedictionary["gridDirFileDataModified"]);
grid.Columns.Add((GridViewColumn)myresourcedictionary["gridDirFileSize"]);
ListViewOp.View = grid
}));
How to create a BitmapImage buffer in background thread on C#?
You're creating something on a non ui thread that by default has thread affinity.
Luckily though, a bitmapimage inherits from freezable.
See the inheritance chain:
https://learn.microsoft.com/en-us/dotnet/api/system.windows.media.imaging.bitmapimage?view=net-5.0
Inheritance:
Object
DispatcherObject
DependencyObject
Freezable
Animatable
ImageSource
BitmapSource
BitmapImage
If you call .Freeze() on a freezable then you can pass it between threads.
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/freezable-objects-overview?view=netframeworkdesktop-4.8
From there:
What Is a Freezable?
A Freezable is a special type of object that has two states: unfrozen and frozen. When unfrozen, a Freezable appears to behave like any other object. When frozen, a Freezable can no longer be modified.
A Freezable provides a Changed event to notify observers of any modifications to the object. Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.
Related Topics
How to Convert String to Integer in C#
Net Core: Execute All Dependency Injection in Xunit Test for Appservice, Repository, etc
"Not In" Clause in Linq to Entities
How to Have a Loop in a Windows Service Without Using the Timer
Patch Async Requests with Windows.Web.Http.Httpclient Class
When Is It Ok to Catch an Outofmemoryexception and How to Handle It
Iequalitycomparer for Sequenceequal
Excel Interop: _Worksheet or Worksheet
How to Intercept Console Output
Why Is This Code Invalid in C#