大家好我想把第三方功能包装到Task就可以等待完成回调功能了。这就是我想要实现的目标..
public MyClass MyProperty {
get
{
if (myProperty == null)
myProperty = LoadMyValue("1234");
return myProperty ;
}
set
{
myProperty = value;
}
}
public MyClass LoadMyValue(string id) {
return MyClassTools.LoadMyValue(id);
}
和MyClassTools
static public MyClass LoadMyValue(string id) {
3rdPartyApi.Call(id, Callback);
// here I want to return Callback result
}
static MyClass Callback(3rdPartyResult result) {
return new MyClass(result);
}
有没有人知道如何在这里使用Tasks和async / await能够直接从函数LoadMyValue返回回调结果?
答案 0 :(得分:5)
正如Noseratio建议的那样,您可以使用TaskCompletionSource<T>
来包装异步API:
public static Task<3rdPartyResult> CallAsync(string id)
{
var tcs = new TaskCompletionSource<3rdPartyResult>();
3rdPartyApi.Call(id, result =>
{
if (result.Exception == null) // or whatever
tcs.TrySetResult(result);
else
tcs.TrySetException(result.Exception);
});
return tcs.Task;
}
然后,您可以使LoadMyValue
成为异步方法:
static public async Task<MyClass> LoadMyValueAsync(string id)
{
return new MyClass(await CallAsync(id));
}
但是,这不会帮助您从属性中返回值。属性不能是异步的。在你的情况下,看起来你想要一个&#34;异步懒惰&#34;值类型,您可以这样做:
private readonly Lazy<Task<MyClass>> myProperty =
new Lazy<Task<MyClass>>(() => LoadMyValueAsync("1234");
public Lazy<Task<MyClass>> MyProperty
{
get { return myProperty; }
}
请注意,我删除了setter,因为语义对于异步延迟评估的属性没有意义。
然后您可以使用以下属性:
MyClass value = await MyProperty.Value;
有一些类型可以使代码稍微容易一些。例如,Noseratio's type for callback wrapping或Stephen Toub的AsyncLazy<T>
(也是我AsyncEx library的一部分)。