应该如何实现 WinRT 对象中的异步回调?
How should an async callback in a WinRT object be implemented?
到目前为止我可以创建一个委托类型,例如:
// Can't use Task in WinRT interface and TypedEventHandler doesn't work with async await
public delegate IAsyncOperation<string> AsyncEventHandler(object sender, object args);
然后像这样在 WinRT 对象中公开:
public AsyncEventHandler OnMyEvent { get; set; }
在 WinRT 对象中,我会这样称呼它:
if (OnMyEvent != null)
{
var result = await OnMyEvent.Invoke(this, someArgs);
// Do something with the result...
}
使用 WinRT 对象的客户端代码可以这样做:
instanceOfWinRTObject.OnMyEvent = OnCalledBackFromWinRT;
但是因为委托 returns 一个 IAsyncOperation
我们需要做一些包装:
private async Task<string> OnCalledBackFromWinRTAsync(object sender,
object args)
{
return await GetSomeStringAsync(args);
}
private IAsyncOperation<string> OnCalledBackFromWinRT(object sender, object args)
{
return OnCalledBackFromWinRTAsync(sender, args).AsAsyncOperation();
}
感觉必须有一种更简洁的方法来实现这一点。
这是由 Peter Torr 的评论提示的替代方法。
// Custom event args class
public sealed class MyEventArgs
{
public string Result;
public Deferral Deferral;
}
// Declare the event handler on the WinRT component
public event TypedEventHandler<object, MyEventArgs> OnSuspendingEvent;
然后在 WinRT 组件中,您可以像这样调用事件:
if (OnSuspendingEvent != null)
{
var tcs = new TaskCompletionSource();
using (var deferral = new Deferral(() => tcs.SetResult(true)))
{
var myArgs = MyEventArgs();
myArgs.Deferral = deferral;
OnSuspendUnloading.Invoke(this, myArgs);
await tcs.Task;
DoSomethingWithResult(args.Result);
}
}
最后在客户端代码中添加一个处理程序,如下所示:
instanceOfWinRTObject.OnSuspendingEvent += async (sender, args) =>
{
var deferral = args.Deferral;
try
{
// Client does some async work with a result
args.Result = await GetSomeStringAsync(args);
}
finally
{
deferral.Complete();
}
}
到目前为止我可以创建一个委托类型,例如:
// Can't use Task in WinRT interface and TypedEventHandler doesn't work with async await
public delegate IAsyncOperation<string> AsyncEventHandler(object sender, object args);
然后像这样在 WinRT 对象中公开:
public AsyncEventHandler OnMyEvent { get; set; }
在 WinRT 对象中,我会这样称呼它:
if (OnMyEvent != null)
{
var result = await OnMyEvent.Invoke(this, someArgs);
// Do something with the result...
}
使用 WinRT 对象的客户端代码可以这样做:
instanceOfWinRTObject.OnMyEvent = OnCalledBackFromWinRT;
但是因为委托 returns 一个 IAsyncOperation
我们需要做一些包装:
private async Task<string> OnCalledBackFromWinRTAsync(object sender,
object args)
{
return await GetSomeStringAsync(args);
}
private IAsyncOperation<string> OnCalledBackFromWinRT(object sender, object args)
{
return OnCalledBackFromWinRTAsync(sender, args).AsAsyncOperation();
}
感觉必须有一种更简洁的方法来实现这一点。
这是由 Peter Torr 的评论提示的替代方法。
// Custom event args class
public sealed class MyEventArgs
{
public string Result;
public Deferral Deferral;
}
// Declare the event handler on the WinRT component
public event TypedEventHandler<object, MyEventArgs> OnSuspendingEvent;
然后在 WinRT 组件中,您可以像这样调用事件:
if (OnSuspendingEvent != null)
{
var tcs = new TaskCompletionSource();
using (var deferral = new Deferral(() => tcs.SetResult(true)))
{
var myArgs = MyEventArgs();
myArgs.Deferral = deferral;
OnSuspendUnloading.Invoke(this, myArgs);
await tcs.Task;
DoSomethingWithResult(args.Result);
}
}
最后在客户端代码中添加一个处理程序,如下所示:
instanceOfWinRTObject.OnSuspendingEvent += async (sender, args) =>
{
var deferral = args.Deferral;
try
{
// Client does some async work with a result
args.Result = await GetSomeStringAsync(args);
}
finally
{
deferral.Complete();
}
}