我仍然是异步/等待新手,但我认为我对它有了更好的把握。我正在写关于如何处理某个场景的建议。方案是,某个Web服务具有同步和异步版本的方法,但版本具有不同的返回类型。
getDocs()
返回document[]
,这就是我想要的。
getDocsAsync()
返回Task<getDocsResponse>
,其中getDocsResponse
具有document[]
类型的(不等待)属性。
为了使问题更复杂,我在委托中调用此方法,我将传递给另一个方法。 (我这样做,所以我可以随意从服务器获取新数据,或者使用我从之前调用中缓存的已保存数据。使用保存数据的委托基本上是Task.FromResult(myDocArray)
。无论是新的还是缓存,我有更多的代码将处理document
个对象。)
主要问题是,如果我调用异步版本,我可以等待返回值的属性吗?如果是这样,怎么样?如果没有,我是否必须等待结果获取属性(如response.Result
)?
(简体)代码示例:调用sync方法,但包装在任务中。这似乎可以正常工作,如果没有getDocs
方法的异步版本,我会怎么做。
Func<Task<document[]>> f = async () => {
var docs = Task.Run(() => service.GetDocs());
return await docs;
}
(简体)代码示例:调用异步版本,然后......?
Func<Task<document[]>> f = async () => {
var docs = service.GetDocsAsync();
// this seems silly to call .Result, only to wrap it in an awaitable task.
return await Task.FromResult(docs.Result.documents);
}
两个版本看起来都运行正常,但在这种情况下,异步路由似乎很尴尬。有没有更好的方法来处理这种情况?
谢谢!
答案 0 :(得分:1)
请勿在{{1}}之前使用.Result
,因为在大多数情况下会导致死锁(await vs Task.Wait - Deadlock?,await works but calling task.Result hangs/deadlocks)
我想您只想从异步委托中返回await
:
documents
请注意,异步方法的结果始终为Func<Task<document[]>> f = async () => {
Task<getDocsResponse> task = service.GetDocsAsync();
getDocsResponse response = await task;
return response.documents;
}
,无论您Task<>
的类型是什么。您不需要将结果包装在return
中。
Task.FromResult
签名但只有同步方法时, FromResult
非常有用。因此,您可以同步重写同步调用(除非您确实需要异步代码,但通常不推荐练习 - What is the best way for wrapping synchronous code into asynchronous method)
Task<T>