I would like to know the difference between using EventHandler<T> and Progress<T>. Are there any situations in which one is a better choice?
When dealing with async Tasks I often see an EventHandler<T> progressChangedCallback that people use to subscribe to a ProgressChanged event of an object and report progress change to e.g. a progress bar on the UI. I also see people passing IProgress<T> instances to the Tasks as parameters. The difference is that they don't invoke an event, they call the IProgress<T>.Report() method instead.
They're different mechanisms. An event is defined on a class, and a IProgress<T> is passed to the async operation itself. An event might make more sense when only 1 async operation is happening at a time, and the progress of every such operation needs to be displayed in the same way, as the UI needs to subscribe to a single event once, and all progress updates from it are handled the same way. An IProgress<T> might make more sense when you can have multiple async operations on the go at once, as it lets you understand which progress is being reported by which operation.
Note that the Progress<T> does the nice thing of dispatching progress updates back to the UI thread (if used in the right way), but events don't do this.
Related
I'm using the async / await pattern to perform some CPU heavy operations on an object (my method is awaitable), which works as supposed without blocking the UI thread.
However, when i pass the object as a parameter to the ctor of a new window (the new window is a logging window that needs access to the processed object), my UI thread blocks (which I kinda understand why).
to get around this I could wrap the execution of the calculation in a
Task.Run(async () => { await _myObject.PerformCalculations(); });
and then simply call
var logWindow = new LogWindow(_myObject);
logWindow.Show();
This works (of course) but i have a lot of dispatcher calls when the object raises events, which I wouldn't have to deal with if I could do without the Task.Run call.
So, my question is, can I somehow do without the Task.Run call and still pass the object to the logging window without blocking my UI thread?
EDIT
I'm sorry for the stripped down example, I actually intended to make the question as simple as possible to understand and failed miserably.
In a more general way: I have an object that raises events on certain conditions. When an event is raised, I want to perform updates on the UI. An event always fires from the thread that was created using Task.Run(...). Hence, dispatcher calls to the UI thread. So, I want to perform the calculations using async / await (already works) and pass the object to my logging window (blocks).
When I use Task.Run, everything works of course, but wherever I subscribe to an event of the object from the UI thread I have to use dispatcher calls to the UI thread, because the event fires from the thread that Task.Run created. These dispatcher calls I would like to avoid. In fact, if I wouldn't pass the object to the logging window, and call the Show() method, the UI thread wouldn't block and everything would work as supposed. No dispatcher calls needed in the event handlers.
It's kind of hard to get a clear picture of your situation. But it looks to me like you could do with some refactoring.
Consider PerformCalculations: this is a method returning Task (thus advertising itself as async-friendly) that does heavy CPU usage (thus not actually being async-friendly). The first thing I would look at is dividing up the logic in PerformCalculations so that the CPU-bound portions use their own Task.Run, leaving PerformCalcuations as an async method that doesn't (directly) hit the CPU:
public async Task PerformCalculationsAsync()
{
while (...)
{
await Task.Run(<next calculations>);
RaiseEvent();
}
}
The point of this refactoring is to divide the CPU code in Task.Run from the UI-ish code raising events. Also consider using the standard IProgress<T> approach if your events are logically progress updates or if this kind of refactoring would be too difficult for your code; IProgress<T>.Report can be called from any thread.
You may also find my posts on async constructors and async properties (particularly the data-binding section) to be helpful.
// awaitable as well - await this in another async void/Task method (e.g. commanding)
public async Task MyAsyncProcess()
{
await _myObject.PerformCalculations();
var logWindow = new LogWindow(_myObject);
}
Task.Run() executes an asynchronous method synchronously, so in this case you pretty much lack of use of the async/await pattern. Make the method where you execute your code async as well and await it somewhere else. Or alternatively use some FireAndForget logic.
I want to achieve something life below -
My application will start UI Module, from UI module I will initiate core module. Core module will keep on running on different thread. On specific action in core module, I want to raise and event which will be subscribed by UI module.
Basically, I want to send specific enum information to UI module.
Please suggest me a model for it. I am trying to achieve it.
Will both module run with any blocking in this model?
Thanks in advance
You can use the Progress class with the IProgress interface to do exactly this.
In your UI context create a Progress object with a generic argument of whatever data you need to pass.
Subscribe to it's event to do whatever you want to do when the background task updates you.
Have the background task accept an object of type IProgress (which Progress implements) and have it periodically Report with the relevant data.
The ProgressChanged event will be fired whenever Report is called, and the Progress object will capture the current synchronization context of where it was created, which is a fancy way of saying that the event will be fired in the UI thread.
I would recommend using the BackgroundWorker Class
Checkout this tutorial
http://www.dotnetperls.com/backgroundworker
Class reference
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Here how it goes in simple ways:
Open your UI form (design view)
Add a backgroundworker control on your UI form
Open the properties pane and switch to events (lightning bolt icon)
Double click on dowork and runworkercompleted events (this will generate event handlers)
Go to the event handlers (in code)
Now write your processing code in dowork handler and add the result you want to send to your ui module like so e.Result = your_enum (or any other Object);
Next come to the runworkercompleted handler and typecast the RunWorkerCompletedEventArgs e (RunWorkerCompletedEventArgs object) to your enum (or object you returned from the dowork handler) and use it in UI as needed.
Finally do not forget to initiate the backgroundworker : backgroundWorker1.RunWorkerAsync() from your UI mdoule
Remark: If you need to report progress periodically use the ReportProgress method of BackgroundWorker class. There are two overloads for this method:
1) http://msdn.microsoft.com/en-us/library/ka89zff4.aspx
2) http://msdn.microsoft.com/en-us/library/a3zbdb1t.aspx
The first one allows to report only the progress percentage and the second one you can use to pass in any object also if you will
This should be pretty easy to do with either the System.Threading.Thread or BackgroundWorker or Task class. You can use either of those to run code on another thread.
When you need to notify the UI, just raise an event. To build events, take a look here:
How can I make my own event in C#?
Then you just need to make sure to call Invoke to make sure that you execute the final UI update code on the correct thread. For that, take a look at this:
Thread Control.Invoke
Sounds like a classic use of the Mediator pattern to me. The Mediator allows disconnected components to talk to each other.
I just happen to have a copy of this in my own MVVM framework, which you can grab from here :
http://cinch.codeplex.com/SourceControl/changeset/view/70832#796984
Also grab this
http://cinch.codeplex.com/SourceControl/changeset/view/70832#797008
My implementation allows you to do it using WeakReference so no strong references are held. Its also allows subscribers to hook up methods to listen to certain events using attributes, and publishers to broadcast a new messaage of T.
Publisher/Subscriber simply register with Mediator
//done by both subscriber and publisher
Mediator.Instance.Register(this);
//Subscriber
[MediatorMessageSinkAttribute("DoBackgroundCheck")]
void OnBackgroundCheck(string someValue) { ... }
//publisher might typically do this
mediator.NotifyColleagues("DoBackgroundCheck", "Nice message");
You may need to use your own SynchronizationContext when subscriber gets message (WPF / Winforms have pre built ones of these) to dispatch call to correct thread.
I also allow for synchronise/aysynchronise calls
I have a library that is a complicated arbiter of many network connections. Each method of it's primary object takes a delegate, which is called when the network responds to a given request.
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete. Creating this object requires a function for the task to represent - As far as my understanding, it is essentially a lightweight thread.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function. Is this possible? Should i avoid abusing the "async/await" pattern in this way?
I don't know if I'm wording this very well, I hope you understand my meaning. Thank you for any help.
As far as my understanding, it is essentially a lightweight thread.
No, that's not really true. I can be true, under certain circumstances, but that's just one usage of Task. You can start a thread by passing it a delegate, and having it execute it (usually asynchronously, possibly synchronously, and by default using the thread pool).
Another way of using threads is through the use of a TaskCompletionSource. When you do that the task is (potentially) not creating any threads, using the thread pool, or anything along those lines. One common usage of this model is converting an event-based API to a Task-based API:
Let's assume, just because it's a common example, that we want to have a Task that will be completed when a From that we have is closed. There is already a FormClosed event that fires when that event occurs:
public static Task WhenClosed(this Form form)
{
var tcs = new TaskCompletionSource<object>();
form.FormClosing += (_, args) =>
{
tcs.SetResult(null);
};
return tcs.Task;
}
We create a TaskCompletionSource, add a handler to the event in question, in that handler we signal the completion of the task, and the TaskCompletionSource provides us with a Task to return to the caller. This Task will not have resulted in any new threads being created, it won't use the thread pool, or anything like that.
You can have a Task/Event based model using this construct that appears quite asynchronous, but only using a single thread to do all work (the UI thread).
In general, anytime you want to have a Task that represents something other than the execution of a function you'll want to consider using a TaskCompletionSource. It's usually the appropriate conceptual way to approach the problem, other than possibly using one of the existing TPL methods, such as WhenAll, WhenAny, etc.
Should I avoid abusing the "async/await" pattern in this way?
No, because it's not abuse. It's a perfectly appropriate use of Task constructs, as well as async/await. Consider, for example, the code that you can write using the helper method that I have above:
private async void button1_Click(object sender, EventArgs e)
{
Form2 popup = new Form2();
this.Hide();
popup.Show();
await popup.WhenClosed();
this.Show();
}
This code now works just like it reads; create a new form, hide myself, show the popup, wait until the popup is closed, and then show myself again. However, since it's not a blocking wait the UI thread isn't blocked. We also don't need to bother with events; adding handlers, dealing with multiple contexts; moving our logic around, or any of it. (All of that happens, it's just hidden from us.)
I want to translate my library to use the new .NET 4.5 "async/await" pattern; this would require me to return a "Task" object, which would signal to the user that the asynchronous part of the call is complete.
Well, not really - you can return anything which implements the awaitable pattern - but a Task is the simplest way of doing this.
This doesn't really fit the design of my library - I would like the task to behave more like an event, and directly signal to the user that their request has completed, rather then representing a function.
You can call Task.ContinueWith to act as a "handler" to execute when the task completes. Indeed, that's what TaskAwaiter does under the hood.
Your question isn't terribly clear to be honest, but if you really want to create a Task which you can then force to completion whenever you like, I suspect you just want TaskCompletionSource<TResult> - you call the SetResult, SetCanceled or SetException methods to indicate the appropriate kind of completion. (Or you can call the TrySet... versions.) Use the Task property to return a task to whatever needs it.
Have just had an idea, I haven't seen it before, wondering if you guys thought it was a good idea, if it exists, any common pitfalls etc. - and also how to implement it.
There are several times I've found myself subscribing to an event from the UI thread that will be called from a different thread - for example, notification of a service call completing.
'My' idea would be to store the current Dispatcher in the add block along with the handler delegate, then when the event is 'fired', perform some extra logic/checks to see if there was a dispatcher associated with the handler, and Invoke on it if necessary.
Of course it would only work on threads with a Dispatcher (or Forms equivalent - something with a message pump I guess). I guess the usefulness and cleanliness depends on whether the event subscriber should have to worry about the thread the handler is called or not?
Edit: Sounds like it's not such a bad thing then - additionally does anyone have any idea how to implement? Using Delegate.Combine how could you call each handler on a different Dispatcher, for example? Would you instead store delegates in a composite object in a List, and invoke them in turn in the On(Whatever) method, or is there something nicer?
...Looking at the BackgroundWorker source in Reflector, there's nothing to Invoke:
protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
{
ProgressChangedEventHandler handler = (ProgressChangedEventHandler) base.Events[progressChangedKey];
if (handler != null)
{
handler(this, e);
}
}
Unless I'm missing something?
So then BackgroundWorker does it with an AsyncOperation. How about a general solution, just for event handlers, in the event accessors? BackgroundWorker can get away with the way it works because a method is called from the client - in the more general case, the only time you'll have access to the handler's thread is in the event accessor? :)
As far as I know, that's exactly what the BackgroundWorker is doing in its RunWorkerCompleted and ProgressChanged events. So it can't be that bad.
I can't find a real proof, that the BackgroundWorker is doing it, I just read it somewhere. When you google for it, you will find more hints. If someone can provide a link, I would be happy.
UPDATE:
Because it isn't so easy to find this behavior in the BackgroundWorker, I provide my analysis:
The BackgroundWorker is using an AsyncOperation for raising the events. Inside this class, the events are posted to a SynchronizationContext. Only then are the methods OnProgressChanged and OnRunWorkerCompleted executed. This means, those methods are already executed on the right thread.
In some more detail, the following happens, when RunWorkerAsync is called:
An AsyncOperation instance is created via AsyncOperationManager.CreateOperation. This saves the current SynchronizationContext. As we are still in the UI thread, this is the context of the UI thread.
The background operation is started and calls into the private method WorkerThreadStart. This method is running in the background thread and executes OnDoWork which in turn raises the DoWork event. This means, the DoWork event is not raised in the UI thread.
After OnDoWork completed, the PostOperationCompleted method of the AsyncOperation instance is executed which in turn calls AsyncOperation.Post which calls SynchronizationContext.Post which in turn will call indirectly OnRunWorkerCompleted on the UI thread.
When ReportProgress is called, a similar thing happens: AsyncOperation.Post is called directly and will invoke the OnProgressChanged method on the UI thread.
AsyncOperation and AsyncOperationManager are public and can be used to implement a similar behavior in your classes.
I've done something similar with Castle DynamicProxy, where it intercepts calls and does an IsInvokeRequired/Invoke on them.
I have a class containing a worker thread which receives data from a queue in a loop.
Another part of the app sinks an event from this class, which the class raises for each queue item.
These events are fired asynchronously, so at busy times the other part of the app can be processing several events at once.
This should be fine but we've discovered a scenario where this can cause problems.
We need a quick solution while the main issue gets addressed. Does the framework provide a simple way I can force the worker thread to wait while each event gets processed (so they are processed sequentially)? If not, what's the easiest way to implement this?
A simple answer would be to lock() on a single object in the event handler. All of the theads would wait to get the lock.
The ManualResetEvent class might help you here, unless I'm not understanding your question. You can use it to block the firing of the next event until the last one completes.
My guess is that you want to simply go away from triggering the action by raising an event and calling the method directly.
AFAIK events are going to be async and I am not aware of any "easy" ways of changing that.
Turns out there's another answer. You can just add the following attribute to the method.
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
There is no general way.
In the end the handlers need to provide a mechanism for tracking.
If you are using BeginInvoke, rather than raising the events directly, you can use a wrapper, within which you call the real event handler synchronously, then raise the wrapper asynchronously. The wrapper can maintain a counter (with Interlocked operations) or set an event as meets your needs.
Something like:
TheDelegate realHandler = theEvent;
var outer = this;
ThreadPool.QuereUserWorkItem(x => {
// Set start of handler
realHandler(outer, eventArgs);
// Set handler finished
};
All of the event handlers sinking events raised by the queue-reading worker thread are called in the queue-reading worker thread. As long as the event handlers aren't spawning threads of their own, you should be able to wait for the event handlers to finish by calling Thread.Join() on the queue-reading worker thread.