Reputation: 76153
I'm using a multi-threaded library that does not use async
, but rather uses traditional threads and callbacks.
var connection = new SomeLib();
connection.OnConnected += (x) => { /* This is called from separate thread */ }
connection.Connect();
I am calling this code from an async
function, like so:
public async Task<Boolean> MyFunc()
{
var connection = new SomeLib();
connection.OnConnected += (x) => { /* This is called from separate thread */ }
connection.Connect();
// ...
// Need to return after OnConnected has been fired.
return true;
}
How can I use await
to have my function "wait" for the OnConnected
callback to be called?
Upvotes: 0
Views: 266
Reputation: 4847
The following will work for EventHandler<> type events - but you can easily adjust them to work for different signature delegates.. First, the helper function (EventToATaskAsync) which takes an adder and remover delegates to set/unset the event:
Note that the downside of using this mechanism is that you need to write an extension method per wrapped async operation.
public static Task<A> EventToTaskAsync<A>(Action<EventHandler<A>> adder, Action<EventHandler<A>> remover)
{
System.Threading.Tasks.TaskCompletionSource<A> tcs = new TaskCompletionSource<A>();
EventHandler<A> onComplete = null;
onComplete = (s, e) =>
{
remover(onComplete);
tcs.SetResult(e);
};
adder(onComplete);
return tcs.Task;
}
Then, I usually wrap it with an extension call to add the Task functionality to the existing class. In the following example, I am adding BeginAsync to a storyboard (but you can do that to pretty much anything that uses the event mechanism):
public static Task BeginAsync(this Storyboard storyboard)
{
return EventToTaskAsync<object>(
e => { storyboard.Completed += e; storyboard.Begin(); },
e => storyboard.Completed -= e);
}
Hope that helps.
Upvotes: 3
Reputation: 2255
You can do this with a wait handle. First define an AutoResetEvent:
private waitForConnect = new AutoResetEvent(false);
In the OnConnected handler, trigger the handle:
waitForConnect.Set();
In the function that calls connect, wait for the handle to trigger:
connection.Connect();
waitForConnect.WaitOne(); // This will sleep the thread until connected
Upvotes: -1