我被异步/等待宠坏了! 现在正在努力与明确的任务延续
编辑(接受后)
它可能不会立即显现,但@Servy的答案是正确的,而不需要在monodroid下自定义实现Unwrap
– 在我的评论中我说它不存在,但它确实存在。
结束编辑
我正在编写一堆使用我们的RESTful Web服务的应用程序,尽管我认为我知道如何正确使用任务但事实并非如此。 场景是我已经为Windows Store实现了代码 – 使用async/await
我需要为MonoDroid实现几乎相同的东西 – 没有那个(没有我不想使用的构建攻击)。
我已经将这个问题的问题归结为一组简单的异步获取整数的任务,然后,在继续中,触发另一个异步任务,转换从该整数构建的字符串。 在C#5中,这将是:
注意 – 当然我在这里使用Task.FromResult
代替实际的异步代码
private async Task GetStringAsync() { return await GetStringFromIntAsync(await GetIntAsync()); } private async Task GetIntAsync() { return await Task.FromResult(10); } private async Task GetStringFromIntAsync(int value) { return await Task.FromResult(value.ToString()); }
要将此转换为基于延续的模式,我试过这个:
private Task GetStringAsync() { //error on this line return GetIntAsync().ContinueWith(t => GetStringFromIntAsync(t.Result)); } private Task GetIntAsync() { return Task.FromResult(10); } private Task GetStringFromIntAsync(int value) { return Task.FromResult(value.ToString()); }
但是,这是不正确的,因为GetStringFromIntAsync
方法返回一个Task
这意味着continuation最终返回Task<Task>
而不是Task
。
我发现显式等待GetStringFromIntAsync
方法确实有效,但是:
private Task GetStringAsync() { return GetIntAsync().ContinueWith(t => { var nested = GetStringFromIntAsync(t.Result); nested.Wait(); return nested.Result; }); }
问题是,尽管 – 这是正确的方法 – 我是否可以不返回呼叫者等待的某种延续?
我已经使用了相当多的任务 – 但不是像这样将不同类型的任务链接在一起(当然除了async
/ await
之外) – 感觉有点像我在这里生气 – 所以任何帮助都非常感激。
所以,首先,即使你有异步/等待,你的第二个和第三个实现的非异步/等待的重复是你应该做的。 除了一些不必要的开销外,使用它不会增加任何内容。
至于第一种情况,不,你不想使用Wait
。 这将阻止线程而不是允许它返回池。 您只需要解开任务并获得它的内部任务。 您可以使用Unwrap
方法执行此操作:
private Task GetStringAsync() { return GetIntAsync() .ContinueWith(t => GetStringFromIntAsync(t.Result)) .Unwrap(); }
这是一个Unwrap
function,如果您无法使用,可以使用它。
public static Task Unwrap (this Task> task) { var tcs = new TaskCompletionSource (); 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; }
对于完全支持的方法,最好等待官方的异步/等待支持MonoDroid – Xamarin已经说过“即将推出” – 今年上半年。
但是,如果你感觉更冒险……那么至少有几个人设法让异步/等待在MonoDroid中工作:
这就是我在.net 4.0(VS 2010)中处理异步任务所做的工作。 有些人说你不需要调用task.Wait();
和其他人说过,是的,你确实需要调用task.Wait();
我认为区别在于task.Wait()是否隐含/封装在task.Result
属性中。
我坚持使用更明确的方法来调用task.Wait();
。
这将阻止,直到调用完成,但如果您不使用4.5,我不确定还有哪些其他选项可用。
上述就是C#学习教程:我被异步/等待宠坏了! 现在正在努力与明确的任务延续分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/955107.html