in order to make UI responsive to User i started to use Multitasking in my Wpf application.
However its confusing for me.
i have seen too much ways of multitasking and now im completely confused what should i do.
BackgroundWorker
seemed ugly way to me so i used Task.Factory.StartNew
my problem is that i cant connect other threads to Main Thread.
Exception : The calling thread cannot access this object because a different thread owns it
i have Global variable that is
private static AssetDeclaration _assetDeclaration = new AssetDeclaration();
this variable is set inside LoadFile
through lock
statement.
First code i wrote did not work. _assetDeclaration
Remains Empty.
Task.Factory.StartNew(() =>
{
Parallel.ForEach(opd.FileNames, LoadFile);//read multiple files together and set values to asset one by one using lock
});
FillTreeView();
LoadAssets();
then i decided to put two other methods in thread.
Task.Factory.StartNew(() =>
{
Parallel.ForEach(opd.FileNames, LoadFile);
Dispatcher.Invoke(FillTreeView);
LoadAssets();
});
now the _assetDeclaration value set correctly.also two other methods works correctly
but Later i cant write ViewPort3D.Children.Add(_modelVisual3Ds[i]);
because _modelVisual3Ds
values are set in another thread (in LoadAssets
Method) and cant be used in MainThread. also i tried Dispatcher.Invoke
but does not work.
also _modelVisual3Ds
members are Freezable. so i freeze them inside thread but they cant be used in Mainthread again.
so can someone explain what is happening?
Edit: i have added more code. to describe. the code is simplified because i cant paste 600 lines of code !
Open file Button:
private void MenuItem_Open(object sender, RoutedEventArgs e)
{
// here user chooses some files to open. and we start opening it!
//...
if (opd.ShowDialog() == true)
{
Task.Factory.StartNew(() =>
{
Parallel.ForEach(opd.FileNames, LoadFile);
Dispatcher.Invoke(FillTreeView);
LoadAssets();
});
}
}
Global Variables:
private static readonly object LockThread = new object(); // to lock
private static AssetDeclaration _assetDeclaration = new AssetDeclaration(); // Class that holds needed files
private static List<ModelVisual3D> _modelVisual3Ds = new List<ModelVisual3D>(); // one of _modelVisual3Ds member must be added to viewport3D children
LoadAssets:
private static void LoadAssets()
{
//...
// i try to freeze each content but they remain not accessible in Main Thread
foreach (ModelVisual3D modelVisual3D in _modelVisual3Ds)
{
modelVisual3D.Content.Freeze();
}
}
Later on loading model in to Viewport3D
ViewPort3D.Children.Add(_modelVisual3Ds[i]);// exception thrown here
"This API was accessed with arguments from the wrong context."