- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
编辑(接受后)
可能不是很明显,但@Servy 的答案是正确的,不需要自定义实现 Unwrap
在 monodroid 下 - 在我的评论中我说它不存在,但它确实存在。
结束编辑
我正在编写一堆使用我们的 RESTful 网络服务的应用程序,尽管我认为我知道如何正确使用任务,但事实证明我不知道。场景是我为 Windows 应用商店实现了代码 - 使用 async/await
我需要为 MonoDroid 实现一些几乎相同的东西——它没有那个(没有一些我不想使用的构建技巧)。
我已经将这个问题的问题归结为一组简单的异步获取整数的任务,然后,在后续中,触发另一个异步任务,该任务将转换从该整数构建的字符串。在 C#5 中,这将是:
注意 - 当然我使用的是 Task.FromResult<T>
在这里代替实际的异步代码
private async Task<string> GetStringAsync()
{
return await GetStringFromIntAsync(await GetIntAsync());
}
private async Task<int> GetIntAsync()
{
return await Task.FromResult(10);
}
private async Task<string> GetStringFromIntAsync(int value)
{
return await Task.FromResult(value.ToString());
}
为了将其转换为基于延续的模式,我尝试了这个:
private Task<string> GetStringAsync()
{
//error on this line
return GetIntAsync().ContinueWith(t => GetStringFromIntAsync(t.Result));
}
private Task<int> GetIntAsync()
{
return Task.FromResult(10);
}
private Task<string> GetStringFromIntAsync(int value)
{
return Task.FromResult(value.ToString());
}
但是,这是不正确的,因为 GetStringFromIntAsync
方法返回 Task<string>
这意味着延续最终会返回一个 Task<Task<string>>
而不是 Task<string>
.
我发现明确等待 GetStringFromIntAsync
方法确实有效,但是:
private Task<string> GetStringAsync()
{
return GetIntAsync().ContinueWith(t =>
{
var nested = GetStringFromIntAsync(t.Result);
nested.Wait();
return nested.Result;
});
}
但问题是 - 这是正确的方法吗 - 我可以不返回调用者随后等待的某种延续吗?
我已经使用了很多任务 - 但不是像这样将不同类型的任务链接在一起(当然除了 async
/await
) - 感觉有点像我在这里要疯了 - 所以任何非常感谢帮助。
最佳答案
所以,首先,即使你有异步/等待,你的第二个和第三个实现的非异步/等待实现也是你应该做的。使用它除了会增加一些不必要的开销外,不会增加任何其他内容。
至于第一种情况,不,你不想使用Wait
。这将阻止线程而不是允许它返回到池中。您只需要打开任务并获得它的内部任务。您可以使用 Unwrap
方法来做到这一点:
private Task<string> GetStringAsync()
{
return GetIntAsync()
.ContinueWith(t => GetStringFromIntAsync(t.Result))
.Unwrap();
}
这是一个 Unwrap
函数,如果您无法使用它,您可以使用它。
public static Task<T> Unwrap<T>(this Task<Task<T>> task)
{
var tcs = new TaskCompletionSource<T>();
task.ContinueWith(t =>
{
t.Result.ContinueWith(innerT => tcs.SetResult(innerT.Result)
, TaskContinuationOptions.OnlyOnRanToCompletion);
t.Result.ContinueWith(innerT => tcs.SetCanceled()
, TaskContinuationOptions.OnlyOnCanceled);
t.Result.ContinueWith(innerT => tcs.SetException(innerT.Exception.InnerExceptions)
, TaskContinuationOptions.OnlyOnRanToCompletion);
}
, TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t => tcs.SetCanceled()
, TaskContinuationOptions.OnlyOnCanceled);
task.ContinueWith(t => tcs.SetException(t.Exception.InnerExceptions)
, TaskContinuationOptions.OnlyOnFaulted);
return tcs.Task;
}
关于c# - 我被 async/await 宠坏了!现在正在为明确的任务延续而苦苦挣扎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14402773/
我是一名优秀的程序员,十分优秀!