我正在使用Windows Phone 8中的Contacts对象,在异步方法中调用SearchAsync。SearchAsync需要订阅SearchCompleted事件处理程序,并通过其中一个事件参数传递其结果,这些结果是异步方法所需的(包括调用其他异步方法)。
你如何等待事件的异步完成,即在事件模式和async/await模式之间建立桥梁?
我能想到的唯一解决方案是使用EventWaitHandle,在awaited Task中等待它,类似于以下内容:
我的实际解决方案(与上面展示的不完全相同)确实可行。虽然上面的代码并不完全代表已实现的解决方案(可能有一两个编译问题),但它应该能够表达概念并阐明我的问题所在。
这让我想知道这是否是唯一的方式,或者接近于最佳实践的方式来等待事件处理程序的执行,如果不是,那么在这里做需要的事情的“最佳实践”是什么。
在异步/等待世界中,Windows同步原语还有用吗?
(基于提供的答案)
这样正确吗?
你如何等待事件的异步完成,即在事件模式和async/await模式之间建立桥梁?
我能想到的唯一解决方案是使用EventWaitHandle,在awaited Task中等待它,类似于以下内容:
using System.Threading;
async Task<string> MyMethod()
{
string result = null;
Contacts cons = new Contacts();
EventWaitHandle handle = new EventWaitHandle(false,EventResetMode.ManualReset);
cons.SearchCompleted += (sender,args) =>
{
// I do all my work on the results of the contact search in this handler
result = SomeOtherSynchronousOperation(args.Results);
// When I'm done, I release the thread which was waiting for the results
handle.Set();
};
cons.SearchAsync(String.Empty, FilterKind.None, "My Contact");
// I can't block this thread (or can I?)
// So, I launch a task whose sole job is to wait
await Task.Run(()=>
{
// This gets released by the Contacts.SearchCompleted handler when its work is finished,
// so that MyMethod can finish up and deliver its result
handle.WaitOne();
}
await DoOtherStuffWithResult(result);
return result;
}
我的实际解决方案(与上面展示的不完全相同)确实可行。虽然上面的代码并不完全代表已实现的解决方案(可能有一两个编译问题),但它应该能够表达概念并阐明我的问题所在。
这让我想知道这是否是唯一的方式,或者接近于最佳实践的方式来等待事件处理程序的执行,如果不是,那么在这里做需要的事情的“最佳实践”是什么。
在异步/等待世界中,Windows同步原语还有用吗?
(基于提供的答案)
这样正确吗?
using Microsoft.Phone.UserData;
string ExtractWhatIWantFromResults(IEnumerable<Contact> results)
{
string result;
// Do my processing on the list of contacts, stuff the results into result
return string;
}
async Task<string> MyMethod()
{
Contacts cons = new Contacts();
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
cons.SearchCompleted += (sender,args) =>
{
tcs.TrySetResult(ExtractWhatIWantFromResults(args.Results));
};
cons.SearchAsync(String.Empty, FilterKind.None, "My Contact");
return tcs.Task;
}