How to await an event handler invocation? - c#

Basically, I have a method which invokes an event handler. the event handler calls an async method and I need to know the results of that method (true or false). since event handlers can only return void, I created my own EventArgs with a success property which I set to true in that method if it goes right.
public virtual async Task<bool> TrySomething()
{
var args = new MyEventArgs();
SomeEvent?.Invoke(this, args);
return args.Success;
}
SomeEvent is hooked up to SomeEventHandler
private async void SomeEventHandler(object sender, MyEventArgs e)
{
e.Success = await AnAsyncMethod();
}
private asyc Task<bool> AnAsyncMethod()
{
//...
}
What I'm confused by is that, is there any guarantee that the method TrySomething will wait for the SomeEvent to finish so Success has been set, before returning it? And if not, how can I ensure that it does?

is there any guarantee that the method TrySomething will wait for the SomeEvent to finish so Success has been set, before returning it?
No. async void means "don't notify the caller when I finish". So the code raising your event cannot know when the event handler has completed, unless you write that additional logic yourself.
And if not, how can I ensure that it does?
Well, that's more of a tricky question. .NET events are designed as what I call "notification events" - that is, when an event fires, it notifies all its listeners. There's no need for "waiting" because there's no way for a listener to provide feedback to the notifier.
Your code is an example of what I call a "command event" - code that is an event but doesn't match the semantics of a notification event. Your code wants a response from the handler.
So, the first question you need to ask yourself is "do I really want this to be an event?" One good litmus test for this is "can I define meaningful semantics if there are multiple handlers?"
More specifically, how should your code behave if multiple handlers are hooked up to the event? Perhaps the answer is "that wouldn't make sense". Or perhaps the answer is "I want to wait for all of them to complete and only be 'successful' if all of them are 'successful'". Or "wait for all and be 'successful' if any of them are 'successful'". Or "wait for the first one to complete and use that result". Or "wait for them to complete one at a time, stopping on the first success". Or "wait for them to complete one at a time, stopping on the first failure". These are the choices that come immediately to mind; there could be more.
If the answer is "that's not going to happen in my code" or "more than one handler doesn't make sense" or "that's too hard of a decision to make right now", then the appropriate answer is to remove the event. It's not an event. It's a method call. In Design Pattern terminology, events are used to implement the Observer Pattern, but what you have is a Strategy Pattern, and that's why events are a poor fit. In this case, you could use Gabriel's answer or something similar where you define the Strategy using an interface, and instead of raising an event you would invoke a method on that interface.
However, if it does make sense to have multiple handlers, and there is a meaningful semantic you can use, then you'll need to modify the EventArgs type to have some sort of "collector" of responses, and then have your event-raising code interpret those responses. The exact code would vary based on the semantics you need.

The whole reason async void is allowed is for event handlers. From the documentation on Async Return Types:
You use the void return type in asynchronous event handlers, which require a void return type.
That said, events are designed to "signal the occurrence of an action" to any interested party, if any (and there can be none, or multiple). Think of it like sending an email notification to whomever subscribed to a specific mailing list: those people might have to do something when they receive the notification, but it's not your concern - you move on to your next task after sending the email. That's all events are. An event handler should not be something that is important for the proper functioning of the object.
Events are not designed to be a "hey this happened, what should I do next?" So there should be no need to await an event handler.
If returning args.Success depends on SomeEventHandler completing successfully, then it shouldn't be an event handler. Instead, you can have a Func<Task<bool>> property (a function that returns Task<bool>). Something like this:
public class SomeClass {
private Func<Task<bool>> IsSuccessful;
public SomeClass(Func<Task<bool>> isSuccessful) {
// Accept a reference to a function and store it
IsSuccessful = isSuccessful;
}
public async Task<bool> DoSomething() {
// Call our function and return the result
return await IsSuccessful();
}
}
Then you could use it like this:
// This is the method we want it to call
private async Task<bool> AnAsyncMethod() {
await Task.Delay(1);
return true;
}
// so we pass it in the constructor of the class.
// You don't have to pass it in the constructor - this is just an example
var myClass = new SomeClass(AnAsyncMethod);
In that way, it's very clear that SomeClass cannot function properly without calling that method and therefore exactly one implementation of that method must be passed into the class.

You could declare the Success property as Task<bool> instead of bool. Then assign it inside the handler like this:
private void SomeEventHandler(object sender, MyEventArgs e)
{
e.Success = AnAsyncMethod(); // Without await
}
At the end you would be able to get the result after invoking the event and awaiting the property.
public virtual async Task<bool> TrySomething()
{
var args = new MyEventArgs();
SomeEvent?.Invoke(this, args);
return await (args.Success ?? Task.FromResult(false));
}

Related

How to raise an event inside a Task?

Let's say I need to implement a C# class library that executes a long-running calculation. When some of the values calculated inside the calculation cross a certain threshold, I have to notify the user, nothing more.
In this case, how do I implement events inside a task? Is that even a proper solution? If not, how can I notify the user of things happening inside my task?
Depending on what you desire to have happen when you say "notify the user", there are quite a few options, some more complex than others (e.g. using a messaging library like RabbitMQ).
However, a simple answer to your question would interpret "notify the user" as meaning "notify the caller of my long running process." In that case, you could create an EventHandler in the class that has your async long running process, and simply call that event handler when you want to "notify" your caller.
Code for the class could look like this:
public class LongTask
{
public event EventHandler StillInProgress;
public async Task<bool> LongRunningProcessAsync()
{
await Task.Delay(5000);
OnStillInProgress(new EventArgs());
await Task.Delay(5000);
return true;
}
protected virtual void OnStillInProgress(EventArgs e)
{
StillInProgress?.Invoke(this, e);
}
}
In the code above, the caller of your long running process could also subscribe to your "StillInProgress" event, and get notifications whenever you call it.
Subscribing to event by caller would look something like this:
var longRun = new LongTask();
longRun.StillInProgress += LongRun_StillInProgress;
// Method that will handle the "notification"
private void LongRun_StillInProgress(object sender, EventArgs e)
{
Debug.WriteLine("InProgress");
}
There are other options, but this is perhaps the most straight-forward.
I've read and experimented more with the problem, and seeing that all I need is to run code on the UI thread when certain conditions of the task are met, it's better to go the IProgress route (Peter Bons and Servy's recommendation). Simpler, better and fully supported. The link posted by Peter Bons (authored by Stephen Cleary) is a great writeup on how to do it.
Thanks to everyone for the help.

Async event handlers with stateful event args

Sometimes we want the event publisher's actions post firing to depend on some state set by the event handlers. A common example is an event that takes CancelEventArgs. The event publisher takes action after firing, conditioned on the value of the Cancel property. If the handler is long running, we don't want to block the UI thread (users can be doing other things while they are waiting). But async handlers may return before the state is set, and the publisher will not have the correct value when it needs it. I solved this by simply providing a mutable Task property in the event argument. It's the responsibility of the handler to set its value, and the publisher to await on it after firing. This seems to work fine.
One objection might be that stateful event args are arguably bad practice, unless you assume only one handler. You could use higher-order functions instead of events, and that would handle the objection above by enforcing one "handler".
One thing that I'm not sure about is how async/await deals with multiple awaiters.
Are there any guarantees about in what order the continuations are executed?
Is there going to be a race condition where the rest of the firing might execute before the rest of the event handler?
Answer is yes. This feels like it's going be an issue for nested async methods generally, whenever the caller and callee both have actions after the await.
Is there anything about the way I'm doing it that has any drawbacks I haven't mentioned?
Is there some other well-known or well-accepted best practice for accomplishing the objective that I'm unaware of?
Any ideas about how to deal with the race condition?
Thanks!
class Publisher
{
void RaiseMyEvent()
{
var e = new MyEventArgs();
OnRaiseMyEvent(e);
if (e.Task != null) await e.HandlerTask;
if (e.Cancel)
{
// Do one thing
}
else
{
// Do the other
}
}
}
class Subscriber
{
void MyEventHandler(object sender, CancelEventArgs e)
{
// Notify user to wait on process
e.Task = SomeAsyncMethod();
await e.Task;
e.Cancel = GetOutcome();
// Clear any notification
}
bool GetOutcome() { }
}
Actually we can avoid a race by ensuring that any needed state values in the event args needed by the firing method are set prior to the continuation in the handler:
class Subscriber
{
void MyEventHandler(object sender, CancelEventArgs e)
{
// Notify user to wait on process
e.Task = Task.Run(() =>
{
//Do stuff
e.Cancel = GetOutcome();
}
await e.Task;
// Clear any notification
}
bool GetOutcome() { }
}
Both continuations execute on the UI thread, but we don't care about the order.
Sometimes we want the event publisher's actions post firing to depend on some state set by the event handlers.
I call these "command events", as opposed to "notification events", and cover a few approaches to async command events on my blog.
After quite a bit of experience, I have come to the conclusion that command events are an anti-pattern. Events in .NET are designed as notification events, and making them behave differently is awkward at best. To use the GoF terminology, .NET events are used to implement the Observer design pattern, but these "command events" are actually an implementation of the Template Method design pattern.
Consider this quote about the Template Method design pattern (pg 328):
It's important for template methods to specify which operations are hooks (may be overridden) and which are abstract operations (must be overridden)
That's a good identifying quality of command events! And if you find yourself writing a .NET event that either requires a handler or can't have more than one handler, then it's a good indication that .NET events are probably the wrong solution.
If you have a Template Method situation, then usually some form of this will suffice as a solution:
interface IDetails { Task ProcessAsync(); }
class Subject
{
private IDetails _details { get; }
public Subject(IDetails details) { _details = details; }
async Task SomeMethodAsync()
{
...
if (_details)
await _details.ProcessAsync();
}
}

C# Events Multiple Publishers to One Subscriber

I have a piece of code that has two event handlers. I want these two event handlers to notify another method that there is some work to be done.
I have implemented this using a ManualResetEvent, but I am unsure if this is the best way to achieve what I want, or if there is some better way.
static ManualResetEvent autoEvent = new ManualResetEvent(false);
void begin() {
ThreadPool.QueueUserWorkItem(new WaitCallback(genericHandler));
}
void OnEvent1(object sender) {
autoEvent.Set();
}
void OnEvent2(object sender) {
autoEvent.Set();
}
void genericHandler(object info) {
while (true) {
autoEvent.WaitOne();
// do some work
}
}
One of the most important questions I have is: After autoEvent.WaitOne(), I do some work and that work consumes time. In the meanwhile, another event is triggered, and Set() is called before the genericHandler gets to WaitOne() again. When WaitOne is reached again, will it wait for another Set(), or proceed if a Set() has been called before reaching the WaitOne()?
Is this the best way to implement multiple publishers and one subscriber pattern in C#? Or should I use another thing instead of the ManualResetEvent?
Note: The genericHandler is in a different thread because Event1 and Event2 have different priorities, so in the handler I check whether Event1 has pending work, before checking Event2.
Your code does indeed do what you think it does, and the race condition you describe is not a problem at all. As per the documentation of a MRE, when it is set it will remain in the "signaled" state until it is reset by a call to WaitOne.
The question and code is presented too vaguely to offer good, specific advice. That said...
No, the use of ManualResetEvent is not appropriate here. Not only does it needlessly complicate the code, your code relies on a long-running thread that you have taken from the thread pool (where only short-lived tasks should be executed).
If you have a need for events to trigger the execution of some asynchronous work, then you should be using the async/await pattern, where each new unit of work is invoked via the Task class.
For example:
async void OnEvent1(object sender) {
var workUnit = ... ; // something here that represents your unit of work
await Task.Run(() => genericHandler(workUnit));
}
void OnEvent2(object sender) {
var workUnit = ... ; // something here that represents your unit of work
await Task.Run(() => genericHandler(workUnit));
}
void genericHandler(object info) {
// do some work using info
}
Note that the event object and the begin() method are eliminated entirely.
It's not clear from your question whether each work unit is entirely independent of each other. If not, then you may also require some synchronization to protect shared data. Again, without a more specific question it's not possible to say what this would be, but most likely you'd either use the lock statement, or one of the Concurrent... collections.

Turn asynchronous calls into synchronous

Is there any good practice (pattern) in turning asynchronous calls into synchronous?
I have a third party library who's methods are all asynchronos, to get result of almoust any method you must listen to an event, which will bring some context with it.
basically it looks like:
service.BeginSomething(...);
service.OnBeginSomethingCompleted += ;
what I need is to execute some code after BeginSomething when it is really complete (thus after OnBeginSomethingCompleted is triggered). It is very inconvinient to handle the response in the event.
The only way I could think of is running a Thread.Sleep loop and wait till some field on the form is updated, but it doesn't look like very elegant sollution.
I'm using .net 4.0.
You could subclass the main class and provide a synchronous version of the operation. If subclassing is not an option you could create an extension method. Here is how things might look.
public class Subclass : BaseClass
{
public void Something()
{
using (var complete = new ManualResetEventSlim(false))
{
EventHandler handler = (sender, args) => { complete.Set(); };
base.OnBeginSomethingCompleted += handler;
try
{
base.BeginSomething();
complete.Wait();
}
finally
{
base.OnBeginSomethingCompleted -= handler;
}
}
}
}
Update:
One thing I should have pointed out is that this could be problematic in some cases. Consider this example.
var x = new Subclass();
x.BeginSomething();
x.Something();
It should be obvious that the handler in Something could receive the OnBeginSomethingCompleted event from the previous call to BeginSomething. Make sure you guard against this somehow.
Use a ManualResetEvent. In your sync wrapper create it, then pass it to the service.BeginSomething() call as part of the state object. Immediately after the call, WaitOne() on it, this will block.
In the service.OnBeginSomethingCompleted event extract it from the state object and set it, this will unblock the sync caller.
As other said, if possible you should try to make your own code async. If that won't work, does your third-party library support the standard BeginXXX, EndXXX async pattern? If so, then using the TPL would make things easy for you. Your code will look something like this:
using System.Threading.Tasks;
...
var task = Task<TResult>.Factory.FromAsync(
service.BeginSomething, service.EndSomething, arg1, arg2, ..., null);
task.Wait();
var result = task.Result;
The specific overload you'll want to use will depend on how many parameters you need to pass. You can see the list here.
If BeginSomething() returns an IAsyncResult (like a delegate's .BeginInvoke would do), you can get the WaitHandle from that:
service.OnBeginSomethingCompleted += ;
var asyncResult = service.BeginSomething();
asyncResult.AsyncWaitHandle.WaitOne(); // Blocks until process is complete
By the way, by assigning the event handler after starting the async process, you are introducing a race condition where the async call may complete before the event is registered, causing it to never fire.
You might want to look at Reactive Extensions
With Rx you can wrap that into an 'event' basically - the do something like someClass.SomeEvent.Subscribe(d=>...) to subscribe using usually some lambda expression to handle what you need. Also use ObserveOn to handle it on the GUI thread (see the details, this is just a hint).
Other option is to use async await (which is now available for use with VS 2010).
hope this helps
NOTE: Rx have a native support for async methods and turning them into Rx events with pretty much just one call. Take a look at Observable.FromAsyncPattern FromAsyncPattern
The general trend of modern software development (on Windows platform too) is to run, what is possible asynchroniously.
Actually from Windows8 software design guidelines, if the code runs more then 50ms, it has to be asynchronious.
So I would not suggest to block the thread, but instead benefit from that library and provide to the user with some nice looking animation saying "wait, responce comming", or something like this, or some progress bar.
In short, do not block thread, notify a user about what is going on in app and leave it async.
This solution is similar to Brian Gideon's, but I think a little bit cleaner for what you're trying to do. It uses the Monitor object to cause the calling thread to wait until the Completed event is triggered.
public class SomeClass : BaseClass
{
public void ExecuteSomethingAndWaitTillDone()
{
// Set up the handler to signal when we're done
service.OnBeginSomethingCompleted += OnCompleted;
// Invoke the asynchronous method.
service.BeginSomething(...);
// Now wait until the event occurs
lock (_synchRoot)
{
// This waits until Monitor.Pulse is called
Monitor.Wait(_synchRoot);
}
}
// This handler is called when BeginSomething completes
private void OnCompleted(object source, ...)
{
// Signal to the original thread that it can continue
lock (_synchRoot)
{
// This lets execution continue on the original thread
Monitor.Pulse(_synchRoot);
}
}
private readonly Object _synchRoot = new Object();
}

How to expose async method's event?

I have a webservice method getContactsAsync. I've understood that when it's completed it's supposed to raise an event. How can I (still asynchronously) find out when the method is done and use the result?
public void GetContacts()
{
webService.getContactsAsync()
}
public void GetContactsCompleted(object sender, getContactsAsyncCompletedEventArgs e)
{
contacts = e.Result;
}
I don't get how I'm supposed to use this. The way I can think of is to call GetContacts and then with a while-loop check if contacts != null to know when it has completed. But this will lock up the thread.
Is there some kind of best-practice typical for this situation?
Thanks for reading!
If I'm completely out of it feel free to explain how it actually works :)
Each DoSomethingAsync method has a corresponding DoSomethingCompleted event that is raised when the method finishes. (See Event-based Asynchronous Pattern Overview for more information.) You need to attach your event handler method to the webService.GetContactsCompleted event in order for it to be executed:
public void GetContacts()
{
webService.getContactsCompleted += GetContactsCompleted;
webService.getContactsAsync();
}
// NOTE: Should be a private method.
private void GetContactsCompleted(object sender, getContactsAsyncCompletedEventArgs e)
{ /* ... */ }
(Note that you will need to ensure that the event handler is only attached once, or it will start being invoked multiple times when the method finishes.)
If you are using SOAP-based web services via a Web Reference, this resource may be the ticket.
http://msdn.microsoft.com/en-us/library/wyd0d1e5%28VS.80%29.aspx
Another viable approach is to use the synchronous methods of the service from your own background thread.
I'm not familiar with that method, sounds specific to that web-service. However, to point you in the right direction, most Async methods take in a delegate as a parameter and will call that delegate when it has finished.
Depending on the method, there may be parameters to call for errors, status and so on.
It's hard to get more specific than that without more specific information about your situation.
Take a look at Calling Web Services Asynchronously.
It's a bit hard to figure out from your question where the problem lies.
You can keep track of when the operation completes by setting something in the event handler. In your example code, you're setting contacts, so you could just check if contacts is null.
If you want an asynchronous notification of completion, like an event that triggers when the operation completes, then... er... handle GetContractsCompleted, because that's exactly what it's there for.
If there's something more specific that you'd like (e.g., a WaitHandle that is signalled or a Task that completes when the operation completes), then that can be done but it's a bit more work.

Categories

Resources