I am work my way through different open source projects to get a feel for how people approach the same problem in different ways. This time it's Event Aggregators, specifically Caliburn.Micro's one.
I notice that Rob said that if no thread is supplied that the EA will marshal to the UI thread. The line specifically is:
public static Action<System.Action>
DefaultPublicationThreadMarshaller = action => action();
and then further on:
marshal(() =>
{
*SNIP*
});
What I don't understand his how can you say this will be called on the UI thread, are all actions called on the UI thread unless you specify one that is not? (You can specify which action is called btw, the line above is just if no action is supplied).
Action can be invoked either in the thread that calls it:
Action a = () => Foo();
a.Invoke();
Or it can be invoked asynchronously
Action a = () => Foo();
a.BeginInvoke();
If the event aggregator is configured to use a synchronous call then it is possible that the event gets handled in the UI thread. However it is very unlikely, and usually an event aggregator uses asynchronous execution and the action is executed in a thread pool.
In the code in question there will be a place, where it (internally and not included here) calls either Invoke or BeginInvoke on the action, this is where the difference is.
N.B. This answer is not specific to any particular event aggregator.
Related
The reason for what I'm going to ask here is that Dispatcher.Invoke throws a TaskCanceledException when another thread executes Dispatcher.InvokeShutdown(). Dispatcher.BeginInvoke() does not seem to suffer from this and I wanted to move my codebase from using Dispatcher.Invoke(...) to Dispatcher.BeginInvoke(...). And below I wanted to ask if the following two Work() methods both running on a separate background thread are equivalent? (do any of you see any issues changing the first into the second?):
Work(){
Dispatcher.Invoke(() => {sameFunction()});
//more work
...
}
Work(){
var task = Dispatcher.BeginInvoke((Action)(() => {sameFunction()});
task.Wait();
//more work
...
}
This issue is a direct consequence of the following issue's answer not having functioned as hoped for. It seems that once Dispatcher.InvokeShutdown has been called (once Dispatcher.HasShutdownStarted is true), all calls to Dispatcher.Invoke will end in throwing a TaskCancelledException.
You should use Dispatcher.InvokeAsync instead of Dispatcher.BeginInvoke. BeginInvoke is part of the old API.
Also, never call Wait(), but use await:
await Dispatcher.InvokeAsync()
Using the new API also allows you to cancel operations (Invoke and InvokeAsync only): to fix the exception issue, you should provide a shared CancellationToken, that you associate with the Dispatcher (virtually, with the one you expect to get shutdown), to every invocation.
This way you can cancel the pending and running operations gracefully before you shutdown the Dispatcher.
Dispatcher.InvokeShutdown will abort any running Dispatcher operation, which applies to every synchronous Dispatcher.Invoke execution - hence the TaskCanceledException is being thrown on abortion.
Regarding Dispatcher.InvokeAsync (and Dispatcher.BeginInvoke): your probably don't experience the cancellation exception, because the dispatched operation is still pending due to its asynchronous execution.
This leads to the difference of both Dispatcher invocation examples:
Your first example uses Dispatcher.Invoke. From the documentation you could learn that it executes synchronously. This means, the delegate is executed immediately (pushed to the front of the queue - respecting the assigned priorities).
The second example uses Dispatcher.BegingInvoke (same applies to the modern Dispatcher.InvokeAsync). This method invokes the delegate asynchronously. This means, the delegate is enqueued into the dispatcher queue and executed after all preceeding pending operations in this queue are completed. If you don't await the call, the Dispatcher returns immediately after enqueuing the delegate and execution continues (this is the asynchronous part).
Therfore, the examples are not equivalent. You have to decide if postponing the delegate's execution is reasonable (Dispatcher.InvokeAsync) or not (Dispatcher.Invoke).
I am new to C#, i have read something about threading like begininvoke and eventhandler stuff. but could you explain what's the following code is doing on the richtextbox?
private void Log(LogMsgType msgtype, string msg)
{
rtfTerminal.Invoke(new EventHandler(delegate
{
rtfTerminal.SelectedText = string.Empty;
rtfTerminal.SelectionFont = new Font(rtfTerminal.SelectionFont, FontStyle.Bold);
rtfTerminal.SelectionColor = LogMsgTypeColor[(int)msgtype];
rtfTerminal.AppendText(msg);
rtfTerminal.ScrollToCaret();
}));
}
*is this Invoke similiar to begininvoke?
* in the msdn, it describe it as Executes the specified delegate on the thread that owns the control's underlying window handle.Not quite sure about the meaning of it.
could you explain what's the following code is doing on the richtextbox?
It executes the code in the anonymous method on the UI thread.
is this Invoke similiar to begininvoke?
Yes, but Invoke is synchronous, whereas BeginInvoke is asynchronous. In other words, a call to Invoke will block until the UI thread executes the specified action, whereas BeginInvoke will return immediately, without waiting for the action to be executed by the UI thread.
in the msdn, it describe it as Executes the specified delegate on the thread that owns the control's underlying window handle.Not quite sure about the meaning of it.
In Windows Forms, controls can only be accessed on the thread that created them. So if you're executing something on a different thread, and you perform an action on a control from this thread, you can't do it directly; you need to ask the UI thread to perform this action. That's what Invoke and BeginInvoke are for.
See the following code:
var obs = Observable.Start(() => LongRunningMethodToRetrieveData());
obs.Subscribe(x => MethodThatMustBeOnUIThread(x));
If I am certain that these 2 lines of code are executed on the UI thread, is it necessary to first call ObserveOn(SynchronizationContext.Current)? Or similarly, do I need to check InvokeRequired inside of MethodThatMustBeOnUIThread?
Basically, am I guaranteed with those 2 lines of code that the 'OnNext' will be called on the thread that is creating the subscription?
Thanks.
Edit: Well, I tried in the debugger and 'MethodThatMustBeOnUIThread' is indeed being called from a background thread. Why is this? My assumption now is that the observing happens by default on the thread that the asynchronous method is run on.
You need to get familiar with the default scheduler used by the various Rx methods.
Methods like Observable.Generate do run on the thread that subscribes to the observable.
On the other hand, the Observable.Start method's purpose is to asynchronously call the lamdba action when the observable is subscribed to. It wouldn't be asynchronous if it happened on the UI-thread. So in this case it uses the ThreadPool scheduler.
This can be seen by using Reflector.NET:
public static IObservable<TSource> Start<TSource>(Func<TSource> function)
{
if (function == null)
{
throw new ArgumentNullException("function");
}
return function.ToAsync<TSource>()();
}
public static Func<IObservable<TResult>> ToAsync<TResult>(
this Func<TResult> function)
{
if (function == null)
{
throw new ArgumentNullException("function");
}
return function.ToAsync<TResult>(Scheduler.ThreadPool);
}
So, knowing the scheduler used you must use a form of ObserveOn before calling Subscribe if you want the subscription to run on the UI-thread.
Also, since you are using Rx, I wouldn't use InvokeRequired - that's just mixing asynchronous coding models. Rx has everything you need to play with threads nicely.
I have been playing around with methods of calling of calling a method safely in threadsafe manner in .net 2.0.
My treeview is populated from a call to a database on a separate thread;
Below is my attempt to use my InvokeFunction method ( shown below) ...it works, but I was hoping that there was a nicer way to write this...any thoughts on this?
InvokeFunction(delegate() { TreeView1.Nodes.Clear(); });
delegate void FunctionDelegate();
private delegate void ThreadSafeProcess(FunctionDelegate func);
private void InvokeFunction(FunctionDelegate func)
{
if (this.InvokeRequired)
{
ThreadSafeProcess d = new ThreadSafeProcess(InvokeFunction);
this.Invoke(d, new object[] { func });
}
else
{
func();
}
}
BackgroundWorker is a cleaner solution in .NET 2.0.
It will create a thread for you and take care of synchronization.
You add BackgroundWorker component to you Form in the design mode.
You subscribe to DoWork event. The method subscribed to this will be execute in a background thread when you call backgroundWorker.RunWorkerAsync() in your UI thread.
When you need to interact with UI thread from your background thread you call backgroundWorker.ReportProgress.
This will trigger ProgressChanged event. ProgressChanged event is always executed in UI thread.
You can use userState parameter of backgroundWorker.ReportProgress to pass any data to UI thread. For example in your case the data that is needed to add new TreeView nodes.
You will actually add new nodes inside of ProgressChanged event handler.
Here is the link to MSDN: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx.
Keep in mind you don't have to use percentProgress parameter of the method ReportProgress method. Although it is convenient when you have a progress bar to reflect background work progress.
You dont have to worry abbout thread safety unless you share some state. Functions always receive their parameters on the stack and stack is local for each thread. So functions are not your problem. Instead focus on the state. "TreeView1" objects is a candidate to worry about.
Is there an elegant way to know when a worker thread is done executing so I can access resources it produced?
For example if the worker thread queried a list of SQL Servers using
ServersSqlDataSourceEnumerator.Instance.GetDataSources();
and saved the result in a DataTable variable, what mechanism can I use to know when this DataTable variable has been populated/is available. I don't want to poll ThreadState; it would be ideal to fire an event when it's done so I can perform actions with the result.
Thanks!
You can use a callback mechanism or block on an event to know of completion of an Async operation. See this page for the Asychronous Programming Model in .net - you can call BeginInvoke on any delegate to perform the action in an Async manner.
If you're using the BackgroundWorker type, you can subscribe to the RunWorkerCompleted event.
So fire an event :-P
You could also look at using an AutoResetEvent:
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
What I do in this instance is get the WorkerThread to call a function after it has completed the work, which will invoke the the UI Thread, which can do the work in which you require.
E.g.
private void SetWorkerThreadToDoWork()
{
WorkerThread.Start();
}
private void MyWorkerThreadWork()
{
//This will be on the WorkerThread (called from WorkerThread.Start())
DoWorkFunc();
WorkComplete();
}
private void WorkComplete()
{
if(InvokeRequired == true)
{
//Do the invoke
}
else
{
//Check work done by worker thread
//e.g. ServersSqlDataSourceEnumerator.Instance.GetDataSources();
}
}
If it's a simple process you're using, I'd go for a BackgroundWorkerThread, this comes with it's own events that are fired when work is complete. But if you require to use a Thread, I would either look in to Asynchronous Callbacks or a similar route to that shown above.
You can check my answer on this SO thread
It uses a call back mechanism. When the async operation is done, it will fire the callback method where you can handle the processing that needs to be done post SQL execution.
Use a similar approach to be notified when the asynchronous operation is done.
Hope this helps :)
I don't program in C# but here's what I did with Delphi, maybe you can do it as well with C#.
I have a TThread descendant, and in the "destroy" event I send a message to its creator saying "hey I'm about to die !".
This way its parent (which is the main thread) creates a new one if it needs a new one. To be precise it launches a timer that, when fired, creates a new thread if a new one is needed (sites sucking time (lol) !!).