C# seralization in different thread - c#

I use the XmlSerializer of C# to save and load all models of my application to a file. Because these file operations can take some time, I want do this serialization/deserialization process in a different thread. To do this, I used a delegate and the "BeginInvoke" operation.
The problem is that when all objects are deserialized that they are created by another thread and that all variables in these objects cannot be accessed by the GUI thread.
I know how to access an object from a different thread (by using the Dispatcher.invoke() method) but using this technique to access each variable is not an option in my application.
Is there a solution or easier way to serialize and deserialize objects in a different thread?
Edit:
When all objects are deserialized, the model notifies the view to create UI objects from the deserialized models.
//In the Model:
//when the deserialize operation is ready this handler is executed (not the GUI thread)
void ProjectLoaded(object sender, EventArgs e)
{
ProjectLoadedEventArgs projectLoadedEventArgs = e as ProjectLoadedEventArgs;
m_models = projectLoadedEventArgs.SerializedData.Models;
Notify(null);
}
//In the view:
public void Update(Object o)
{
model.Angle.... -> RIGHT VALUE!!!
Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
ResetCanvas();
model.Angle... -> ERROR: The calling thread cannot access this object because a different thread owns it.
}));
}

Deserializing thread has to store objects in some well known to UI thread place. Remember You will have to come up with some synchronization mechanism between threads.
I think I know why You have problems (I read comment to other answer). You deserialize and then notice UI that object is ready. You probably do sth like
UIComponent.DeserializationFinished(). In this method You modify the UI which is not allowed.

[Edit]
Since you've added the exception ("The calling thread cannot access this object because a different thread owns it") in the comment below, it's now clear that GUI controls are being accessed from a non GUI thread. If you search for this on StackOverflow, you will see that it's the direct consequence of refusing to use Dispatcher.Invoke.
I am afraid that you can do only two things:
The preferred way: Use Dispatcher.Invoke to invoke the async deserialization callback on a GUI thread (I realize you've said it's not an option, but it's actually the best way to do it). Remember that Dispatcher.Invoke doesn't access deserialized objects in any special way, it only invokes the callback handler on a GUI thread:
// your async callback
public void ObjectWasDeserialized(IAsyncResult result)
{
_dispatcher.Invoke(new Action<IAsyncResult>(UpdateSomeControl), result);
}
Don't use async callbacks at all, but a Future pattern as described below. But that forces you to poll the result from a GUI thread, which is a bad thing.
It doesn't matter what thread creates an object, its data is still accessible by other threads. What is not recommended is accessing GUI controls from a different thread.
What you probably need is a thread-safe way to signal the GUI thread that an object is ready to be accessed. That can be implemented as a Future object (as explained in this article by Ayende).
Your background thread should create a wrapper around your object, which also contains a ManualResetEvent set to false. After the object has been deserialized successfully, it should signal the event (ManualResetEvent.Set()). UI thread which wants to access the object will have to do it through a property which blocks on this same event until it's signaled. That's logical, since you cannot guarantee that the object will be ready anytime the GUI thread wishes it.
[Edit] Found the article with an implementation. First part is what I was talking about, and ends by defining the InThe class. The part which follows, however, is not necessary at all, and I don't recommend it.
Using the code provided by Ayende, you would have something like:
// a thread (it can even be a GUI thread) requests a future result
Future<SomeObject> future = InThe.Future<SomeObject>(() => Deserialize(file));
// later, in the GUI thread, you access the future wrapper directly
SomeObject result = future.Value; // this will block the calling thread until
// result is ready

Related

Can't Access Variable Because It Is Owned By Another Thread [duplicate]

A common exception one can get when working with multiple threads in WPF is:
The calling thread cannot access this object because a different thread owns it
What are the options to deal with this properly?
Depending on the situation there are various options:
Accessing a control from another thread
e.g. updating a TextBlock with progress information.
Data Binding:
In this case the easiest thing you can do is avoiding the direct interaction with the control. You can just bind the property you want to access or modify to an object whose class implements INotifyPropertyChanged and then set the property on that object instead. The framework will handle the rest for you. (In general you rarely should need to interact with UI-elements directly, you can almost always bind the respective properties and work with the binding source instead; one case where direct control access may be necessary is control authoring.)
There are some cases where data binding alone is not enough, for example when trying to modify a bound ObservableCollection<T>, for this you need...
Dispatching:
You can dispatch your accessing code to the thread owning the object, this can be done by calling Invoke or BeginInvoke on the Dispatcher owning the object being accessed (getting this Dispatcher is possible on another thread).
e.g.
new Thread(ThisThreadStart).Start();
void ThisThreadStart()
{
textBlock.Dispatcher.Invoke(new Action(() => textBlock.Text = "Test"));
}
If it is not clear on which thread a method is executed you can use Dispatcher.CheckAccess to either dispatch or execute an action directly.
e.g.
void Update()
{
Action action = () => myTextBlock.Text = "Test";
var dispatcher = myTextBlock.Dispatcher;
if (dispatcher.CheckAccess())
action();
else
dispatcher.Invoke(action);
}
If an object is not a DispatcherObject and you still need the associated Dispatcher you can use Dispatcher.CurrentDispatcher in the thread creating the object (so doing this in the method being executed by a thread will not do you any good). For convenience as you usually create objects on the application's main UI thread; you can get that thread's Dispatcher from anywhere using Application.Current.Dispatcher.
Special cases:
BackgroundWorker
Move any control access to ProgressChanged as it occurs on the thread that created the instance (which should of course be the UI-thread)
Timers
In WPF you can use the DispatcherTimer for convenience, it does the dispatching for you so any code in Tick is invoked on the associated dispatcher. If you can delegate the dispatching to the data binding system you of course can use a normal timer as well.
You can read more about how the Dispatcher queue works and WPF threading in general on MSDN.
Accessing an object created on another thread
e.g. loading an image in the background.
If the object in question is not Freezable you should in general simply avoid creating it on another thread or restricting access to the creating thread. If it is Freezable you just need to call Freeze to make it accessible to other threads.
Accessing a data object from another thread
That is, the type whose instance is being updated is user-code. If an exception is thrown this situation probably came about by someone using DependencyObject as base type for a data class.
This situation is the same as accessing a control and the same approaches can be applied but usually it should be avoided in the first place. Granted, this allows for simple property change notifications via dependency properties and those properties can also be bound but often enough this is just not worth giving up thread-independency. You can get change notifications from INotifyPropertyChanged and the binding system in WPF is inherently asymmetrical, there always is a property that is bound (target) and something that is the source for this binding. Usually the UI is the target and the data is the source, meaning that only UI components should need dependency properties.
That would be several hundred lines of code, for something I "figured out".
But the summary is:
App_OnStartup
generate a background thread
in the callback,
Call
Application.Current.MainWindow.Dispatcher.CheckAccess() - gets the exception
Application.Current.Dispatcher.CheckAccess() does not
I have a udp listener object that communicates through events where the method/callbacks are +='ed in my mainWindow wpf .cs file.
The event handler functions are called with parameters, one being the message I want displayed in a listbox in the mainWindow.cs
Using the information in this thread by H.B. above;
I have added, tested and handled the crossthread in wpf in my eventhandler callback using the following code, but I use a real message not a hard coded one:
listBox1.Dispatcher.Invoke(new Action(() => listBox1.Items.Add("MessageHere")));
UPDATE:
This is better because you can put more things in the anonymous function.
listBox1.Dispatcher.Invoke((Action)delegate
{
listBox1.Items.Add(e.ReaderMessage);
});

What does SynchronizationContext do?

In the book Programming C#, it has some sample code about SynchronizationContext:
SynchronizationContext originalContext = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(#"c:\temp\log.txt");
originalContext.Post(delegate {
myTextBox.Text = text;
}, null);
});
I'm a beginner in threads, so please answer in detail.
First, I don't know what does context mean, what does the program save in the originalContext? And when the Post method is fired, what will the UI thread do?
If I ask some silly things, please correct me, thanks!
EDIT: For example, what if I just write myTextBox.Text = text; in the method, what's the difference?
What does SynchronizationContext do?
Simply put, SynchronizationContext represents a location "where" code might be executed. Delegates that are passed to its Send or Post method will then be invoked in that location. (Post is the non-blocking / asynchronous version of Send.)
Every thread can have a SynchronizationContext instance associated with it. The running thread can be associated with a synchronization context by calling the static SynchronizationContext.SetSynchronizationContext method, and the current context of the running thread can be queried via the SynchronizationContext.Current property.
Despite what I just wrote (each thread having an associated synchronization context), a SynchronizationContext does not necessarily represent a specific thread; it can also forward invocation of the delegates passed to it to any of several threads (e.g. to a ThreadPool worker thread), or (at least in theory) to a specific CPU core, or even to another network host. Where your delegates end up running is dependent on the type of SynchronizationContext used.
Windows Forms will install a WindowsFormsSynchronizationContext on the thread on which the first form is created. (This thread is commonly called "the UI thread".) This type of synchronization context invokes the delegates passed to it on exactly that thread. This is very useful since Windows Forms, like many other UI frameworks, only permits manipulation of controls on the same thread on which they were created.
What if I just write myTextBox.Text = text; in the method, what's the difference?
The code that you've passed to ThreadPool.QueueUserWorkItem will be run on a thread pool worker thread. That is, it will not execute on the thread on which your myTextBox was created, so Windows Forms will sooner or later (especially in Release builds) throw an exception, telling you that you may not access myTextBox from across another thread.
This is why you have to somehow "switch back" from the worker thread to the "UI thread" (where myTextBox was created) before that particular assignment. This is done as follows:
While you are still on the UI thread, capture Windows Forms' SynchronizationContext there, and store a reference to it in a variable (originalContext) for later use. You must query SynchronizationContext.Current at this point; if you queried it inside the code passed to ThreadPool.QueueUserWorkItem, you might get whatever synchronization context is associated with the thread pool's worker thread. Once you have stored a reference to Windows Forms' context, you can use it anywhere and at any time to "send" code to the UI thread.
Whenever you need to manipulate a UI element (but are not, or might not be, on the UI thread anymore), access Windows Forms' synchronization context via originalContext, and hand off the code that will manipulate the UI to either Send or Post.
Final remarks and hints:
What synchronization contexts won't do for you is telling you which code must run in a specific location / context, and which code can just be executed normally, without passing it to a SynchronizationContext. In order to decide that, you must know the rules and requirements of the framework you're programming against — Windows Forms in this case.
So remember this simple rule for Windows Forms: DO NOT access controls or forms from a thread other than the one that created them. If you must do this, use the SynchronizationContext mechanism as described above, or Control.BeginInvoke (which is a Windows Forms-specific way of doing exactly the same thing).
If you're programming against .NET 4.5 or later, you can make your life much easier by converting your code that explicitly uses SynchronizationContext, ThreadPool.QueueUserWorkItem, control.BeginInvoke, etc. over to the new async / await keywords and the Task Parallel Library (TPL), i.e. the API surrounding the Task and Task<TResult> classes. These will, to a very high degree, take care of capturing the UI thread's synchronization context, starting an asynchronous operation, then getting back onto the UI thread so you can process the operation's result.
I'd like to add to other answers, SynchronizationContext.Post just queues a callback for later execution on the target thread (normally during the next cycle of the target thread's message loop), and then execution continues on the calling thread. On the other hand, SynchronizationContext.Send tries to execute the callback on the target thread immediately, which blocks the calling thread and may result in deadlock. In both cases, there is a possibility for code reentrancy (entering a class method on the same thread of execution before the previous call to the same method has returned).
If you're familiar with Win32 programming model, a very close analogy would be PostMessage and SendMessage APIs, which you can call to dispatch a message from a thread different from the target window's one.
Here is a very good explanation of what synchronization contexts are:
It's All About the SynchronizationContext.
It stores the synchronization provider, a class derived from SynchronizationContext. In this case that will probably be an instance of WindowsFormsSynchronizationContext. That class uses the Control.Invoke() and Control.BeginInvoke() methods to implement the Send() and Post() methods. Or it can be DispatcherSynchronizationContext, it uses Dispatcher.Invoke() and BeginInvoke(). In a Winforms or WPF app, that provider is automatically installed as soon as you create a window.
When you run code on another thread, like the thread-pool thread used in the snippet, then you have to be careful that you don't directly use objects that are thread-unsafe. Like any user interface object, you must update the TextBox.Text property from the thread that created the TextBox. The Post() method ensures that the delegate target runs on that thread.
Beware that this snippet is a bit dangerous, it will only work correctly when you call it from the UI thread. SynchronizationContext.Current has different values in different threads. Only the UI thread has a usable value. And is the reason the code had to copy it. A more readable and safer way to do it, in a Winforms app:
ThreadPool.QueueUserWorkItem(delegate {
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.BeginInvoke(new Action(() => {
myTextBox.Text = text;
}));
});
Which has the advantage that it works when called from any thread. The advantage of using SynchronizationContext.Current is that it still works whether the code is used in Winforms or WPF, it matters in a library. This is certainly not a good example of such code, you always know what kind of TextBox you have here so you always know whether to use Control.BeginInvoke or Dispatcher.BeginInvoke. Actually using SynchronizationContext.Current is not that common.
The book is trying to teach you about threading, so using this flawed example is okayish. In real life, in the few cases where you might consider using SynchronizationContext.Current, you'd still leave it up to C#'s async/await keywords or TaskScheduler.FromCurrentSynchronizationContext() to do it for you. But do note that they still misbehave the way the snippet does when you use them on the wrong thread, for the exact same reason. A very common question around here, the extra level of abstraction is useful but makes it harder to figure out why they don't work correctly. Hopefully the book also tells you when not to use it :)
The purpose of the synchronization context here is to make sure that myTextbox.Text = text; gets called on the main UI thread.
Windows requires that GUI controls be accessed only by the thread they were created with. If you try assign the text in a background thread without first synchronizing (through any of several means, such as this or the Invoke pattern) then an exception will be thrown.
What this does is save the synchronization context prior to creating the background thread, then the background thread uses the context.Post method execute the GUI code.
Yes, the code you've shown is basically useless. Why create a background thread, only to immediately need to go back to the main UI thread? It's just an example.
SynchronizationContext basically is a provider of callback delegates' execution. It is responsible for ensuring that the delegates are run in a given execution context after a particular portion of code (encapsulated inside a Task object in .Net TPL) in a program has completed its execution.
From technical point of view, SC is a simple C# class that is oriented to support and provide its function specifically for Task Parallel Library objects.
Every .Net application except for console applications has a tailored implementation of this class based on the specific underlying framework, eg: WPF, WindowsForm, Asp Net, Silverlight, etc.
The importance of this object is bound to the synchronization between results returning from asynchronous execution of code, and the execution of dependent code that is waiting for results from that asynchronous work.
And the word "context" stands for execution context. That is, the current execution context where that waiting code will be executed- namely the synchronization between async code and its waiting code happens in a specific execution context. Thus this object is named SynchronizationContext.
It represents the execution context that will look after syncronization of async code and waiting code execution.
To the Source
Every thread has a context associated with it -- this is also known as the "current" context -- and these contexts can be shared across threads. The ExecutionContext contains relevant metadata of the current environment or context in which the program is in execution. The SynchronizationContext represents an abstraction -- it denotes the location where your application's code is executed.
A SynchronizationContext enables you to queue a task onto another context. Note that every thread can have its own SynchronizatonContext.
For example: Suppose you have two threads, Thread1 and Thread2. Say, Thread1 is doing some work, and then Thread1 wishes to execute code on Thread2. One possible way to do it is to ask Thread2 for its SynchronizationContext object, give it to Thread1, and then Thread1 can call SynchronizationContext.Send to execute the code on Thread2.
SynchronizationContext provides us a way to update a UI from a different thread (synchronously via the Send method or asynchronously via the Post method).
Take a look at the following example:
private void SynchronizationContext SyncContext = SynchronizationContext.Current;
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(Work1);
thread.Start(SyncContext);
}
private void Work1(object state)
{
SynchronizationContext syncContext = state as SynchronizationContext;
syncContext.Post(UpdateTextBox, syncContext);
}
private void UpdateTextBox(object state)
{
Thread.Sleep(1000);
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.Text = text;
}
SynchronizationContext.Current will return the UI thread's sync context. How do I know this? At the start of every form or WPF app, the context will be set on the UI thread. If you create a WPF app and run my example, you'll see that when you click the button, it sleeps for roughly 1 second, then it will show the file's content. You might expect it won't because the caller of UpdateTextBox method (which is Work1) is a method passed to a Thread, therefore it should sleep that thread not the main UI thread, NOPE! Even though Work1 method is passed to a thread, notice that it also accepts an object which is the SyncContext. If you look at it, you'll see that the UpdateTextBox method is executed through the syncContext.Post method and not the Work1 method. Take a look at the following:
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread.Sleep(1000);
string text = File.ReadAllText(#"c:\temp\log.txt");
myTextBox.Text = text;
}
The last example and this one executes the same. Both doesn't block the UI while it does it jobs.
In conclusion, think of SynchronizationContext as a thread. It's not a thread, it defines a thread (Note that not all thread has a SyncContext). Whenever we call the Post or Send method on it to update a UI, it's just like updating the UI normally from the main UI thread. If, for some reasons, you need to update the UI from a different thread, make sure that thread has the main UI thread's SyncContext and just call the Send or Post method on it with the method that you want to execute and you're all set.
Hope this helps you, mate!
This example is from Linqpad examples from Joseph Albahari but it really helps in understanding what Synchronization context does.
void WaitForTwoSecondsAsync (Action continuation)
{
continuation.Dump();
var syncContext = AsyncOperationManager.SynchronizationContext;
new Timer (_ => syncContext.Post (o => continuation(), _)).Change (2000, -1);
}
void Main()
{
Util.CreateSynchronizationContext();
("Waiting on thread " + Thread.CurrentThread.ManagedThreadId).Dump();
for (int i = 0; i < 10; i++)
WaitForTwoSecondsAsync (() => ("Done on thread " + Thread.CurrentThread.ManagedThreadId).Dump());
}

MultiThreading COMObject and UI Thread (C#)

This is my first post here as actually i usually solve all my issue with the awesome
post database you can find here. But I'm actually stuck right now:
I'm working on a project following the MVVM including a COM object.
As I read during my research, I understand that the COM object is only accessible from the thread which created it. My COM object implements the following interface
interface IComUpdate
{
void Update();
}
So when I create my COM object, each time there is an update (I dont know when, its random) the COM Server will call the Update() of the COM object class I did implement.
My goal was to create a different thread, naming a COM object thread, where the COM object exist independantly of my UI Thread, so everytime there is an update, I handle it in a different thread than the UI Thread.
Actually it is working:
At the Beginning of my ViewModel I create a collection of a specific object.
This object, lets call it ModelObj, is part of the model and defines a static constructor in which the application, apart from initializing some variables, creates and starts a new thread for the COM object:
Thread t = new System.Threading.Thread(() =>
{
System.Threading.Thread.CurrentThread.Name = "Thread of COM Object";
IComUpdate myComObj;
myComObj = (IComUpdate)Activator.CreateInstance(blabla);
Application.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
It actually works very well, in the Update() implementation of my COM object, I actually see that the thread is the one just created and not the UI thread.
Now the issue is this: this ModelObj I create implements the INotifyPropertyChanged interface.
My thinking was the following: each time the COM object receives an update, I handle data from the COM object thread, and update some property of my ModelObjinstance from this thread, so these properties will then raise the property change of my ModelObj and the UI thread will update the User Interface.
If the UI update takes too much time, I might miss some Update() to appear on the screen but the COM object will have them recorded in my ModelObj instance so it is not very important that the UI catch all the updates, I just didnt want the COM object to have to wait for the UI to be updated to be called again.
I read tons of posts and thought then that my RaisePropertyChanged("property") would fail.
Actually even in the COM object's thread, the RaisePropertyChanged successfully executes, so tracing my code, I see it switches to my ViewModel assembly where I do
// Here I'm still in the thread of my COM object!
base.NotifyOfPropertyChange<string>(() => this.property)
and then the UI Update.
Note: I'm using Caliburn Micro for binding between my View in WPF and my ViewModel.
So I can't trace after this base.NotifyOfPropertyChange<string>(() => this.property). Maybe Caliburn handles the thread switch, this is not really my issue.
What I can say is that my COM object thread waits for the UI to update to get to the next instruction after my RaisePropertyChanged("property"), so it's exactly the same as if the UI thread did the whole work.
I want my COM object thread to update my ModelObj which will send to send the UI a message to update (because some fields of this ModelObj have changed) and continue immediatly, without knowing if the UI actually updates or not.
Does someone got an idea about this behaviour?
Thank you very much.
####UPDATE####
Thanks everyone for such quick answers.
I did actually as Zdeslav Vojkovic suggested :
You should always update GUI from GUI thread
For completeness here is how I did:
Because my View is full WPF with no code behind i dont have any controls or form to be call BeginInvoke from, so in the static constructor of my ModelObj, I built an invisible Control from the UI Thread just to be able to call BeginInvoke on it.
So i declared it :
public static Control mInvokeControl;
delegate void MyDelegate();
private MyDelegate _NotifyDelegate;
and then did this in the static constructor of my Object:
mInvokeControl = new Control();
mInvokeControl.CreateControl();
in the normal constructor i Initialize the delegate this way:
_NotifyDelegate = new MyDelegate(this.NotifyByInvoke);
Then after i just use it this way:
ModelObj.mInvokeControl.BeginInvoke(this._NotifyDelegate );
With the method being:
public void NotifyByInvoke()
{
RaisePropertyChanged("Update");
}
Everything works fine !
the COMObj is only accessible from the thread which created it
this is not true. It depends on objects apartment model, but usually you can access it from any thread and it will be either called on same thread or marshaled to proper thread.
I belive that your problem is that you update GUI from background thread which is a major no-no. You should always update GUI from GUI thread. When you update your model object, it still happens on background thread and event of INotifyPropertyChanged interfaces fires on that thread.
You need to synchronize model update to GUI thread by using something like this (WinForms, not WPF - in WPF you should use frm.Dispatcher.BeginInvoke but the problem is the same):
private delegate void ExecuteActionHandler(Action action);
public static void ExecuteOnUiThread(this Form form, Action action)
{
if (form.InvokeRequired) { // we are not on UI thread
// Invoke or BeginInvoke, depending on what you need
// but you said ' and continue immediatly' so BeginInvoke it is
form.BeginInvoke(new ExecuteActionHandler(ExecuteOnUiThread), action);
}
else { // we are on UI thread so just execute the action
action();
}
}
There is another question with similar problem and I have provided additional details there.
I do not know how much data you process, or how much time it takes to perform the GUI part. You may also consider to use locked queues. You can use a queue within your ModelObj to enqueue new tasks by it. This you do with everything you get. Then you may have a timer thread (on the GUI thread).
Here you just check the locked queue, whether there is some new data to display on the GUI. You may dequeue the full list here locally. Then you can also check, whether there is more than one data to display on one component. This way you can skip updates, where you already have newer updates.
And you skip the time for invoking the gui thread to perform the action. You can do several GUI updates at once. If you have too much things to do, you may dequeue only up to a specific number of items to let the GUI react on user interactions. However, you need to check that the queue is not constantly growing.

C# GUI Application, Another class from another thread updating the UI

I've been researching on how to do this for about a week and I'm still not sure about the correct approach, in some examples I see the Thread class is used in others I see Invoke is used which has confused me a bid.
I have a GUI program in c# which contains a textBox which will be used to give information to the user.
The problem I'm facing is that I'm not sure how I can append text to textBox from another class which is running on another thread. If someone can show me a working example, it would help me greatly.
Best Regards!
Easy:
MainWindow.myInstance.Dispatcher.BeginInvoke(new Action(delegate() {MainWindow.myInstance.myTextBox.Text = "some text";});
WHERE MainWindow.myInstance is a public static variable set to the an instance of MainWindow (should be set in the constructor and will be null until an instance is constructed).
Ok thats a lot in one line let me go over it:
When you want to update a UI control you, as you say, have to do it from the UI thread. There is built in way to pass a delegate (a method) to the UI thread: the Dispatcher. I used MainWindow.myInstance which (as all UI components) contains reference to the Dispatcher - you could alternatively save a reference to the Dispatcher in your own variable:
Dispatcher uiDispatcher = MainWindow.myInstance.Dispatcher;
Once you have the Dispatcher you can either Invoke() of BeginInvoke() passing a delegate to be run on the UI thread. The only difference is Invoke() will only return once the delegate has been run (i.e. in your case the TextBox's Text has been set) whereas BeginInvoke() will return immediately so your other thread you are calling from can continue (the Dispatcher will run your delegate soon as it can which will probably be straight away anyway).
I passed an anonymous delegate above:
delegate() {myTextBox.Text = "some text";}
The bit between the {} is the method block. This is called anonymous because only one is created and it doesnt have a name - but I could instantiated a delegate:
Action myDelegate = new Action(UpdateTextMethod);
void UpdateTextMethod()
{
myTextBox.Text = "new text";
}
Then passed that:
uiDispatcher.Invoke(myDelegate);
I also used the Action class which is a built in delegate but you could have created your own - you can read up more about delegates on MSDN as this is going a bit off topic..
Sounds like you're using a background thread for processing, but want to keep the UI responsive? The BackgroundWorker sounds like the ticket:
The BackgroundWorker class allows you
to run an operation on a separate,
dedicated thread. Time-consuming
operations like downloads and database
transactions can cause your user
interface (UI) to seem as though it
has stopped responding while they are
running. When you want a responsive UI
and you are faced with long delays
associated with such operations, the
BackgroundWorker class provides a
convenient solution.
Just use BackgroundWorker for the same. It is simple and takes away the pain of managing threads of your own. for more, you can see: http://dotnetperls.com/backgroundworker

Threading, how to instantiate multiple threads without using a class structure

What I have is a loop reading some data and when a set of circumstances are met I need to instantiate a thread. However, the created thread might not complete before the loop criteria is met and I need to create another thread doing the same thing. This is part of an ocr app and I haven't done much thread work before.
while loop
if(criteria)
{
observer = new BackgroundWorker();
observer.DoWork += new DoWorkEventHandler(observer_DoObserving);
observer.RunWorkerAsync();
}
the observer_DoObserving function calls the ocr app, waits for a response and then processes it appropriately and sets observer = null at the end. So how would I create multiple instances of the 'observer' thread. Of course instantly I thought of a class structure, is this an appropriate way to do it or is there another way that is appropriate for threading.
I hope this makes sense.
Thanks, R.
You could use the thread pool, specifically ThreadPool.
while (something)
{
if (criteria)
{
// QueueUserWorkItem also has an overload that allows you to pass data
// that data will then be passed into WorkerMethod when it is called
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkerMethod));
}
}
// ...
private void WorkerMethod(object state)
{
// do work here
}
How you handle this depends in large part on whether the background thread needs to communicate anything to the main thread when it's done. If the background thread really is "fire and forget", then there's no particular reason why you need to maintain a reference to the observer. So you could write:
while loop
{
if(criteria)
{
BackgroundWorker observer = new BackgroundWorker();
observer.DoWork += new DoWorkEventHandler(observer_DoObserving);
observer.RunWorkerAsync();
}
}
The thread does its work and goes away. observer is a local variable that goes out of scope when execution leaves the if block. There's no way that the variable will be overwritten if you have to start another observer thread before the first one is finished.
If you need to keep track of information for individual observers, then you'd create an object of some type (a class that you define) that contains information about the worker's state, and pass that to the RunWorkerAsync method. The worker can then modify that object and send you progress notifications (see the ProgressChanged event and the ReportProgress method), and also report the status when the worker has finished (see RunWorkerCompleted, the state object you passed to RunWorkerAsync will be in the RunWorkerCompletedEventArgs.UserState property).
I am not entirely able to grasp what you are doing exactly, so I may or may not be helpful here;
You seem to be, in part, asking if it's appropriate to create a class to hold some data indicating the state of a thread or what it's working on. That is entirely appropriate to do, provided the object is not an 'expensive' one to create. (no creating Exception objects and throwing them around all the time, for instance).

Categories