简体   繁体   English

Web呼叫的C#异步/同步版本返回不同的类型

[英]C# async/sync versions of Web Call return different types

I am still an async/await novice, but I think I am getting a better grip on it. 我仍然是异步/等待新手,但我认为我对此有所了解。 I am writing for suggestions on how to handle a certain scenario. 我正在撰写有关如何处理特定情况的建议。 The scenario is that, a certain web service has a method with both sync and async versions, but the versions have different return types. 场景是,某个Web服务同时具有同步和异步版本的方法,但是这些版本具有不同的返回类型。

getDocs() returns document[] , which is what I want. getDocs()返回document[] ,这是我想要的。

getDocsAsync() returns Task<getDocsResponse> , where getDocsResponse has a (non-awaitable) property of type document[] . getDocsAsync()返回Task<getDocsResponse> ,其中getDocsResponse具有类型为document[]的(不可等待)属性。

To further complicate matters, I am calling this method inside a delegate I am passing to another method. 为了进一步使事情复杂化,我在传递给另一个方法的委托中调用此方法。 (I am doing this so I can, at will, either get fresh data from the server, or use saved data that I have cached from earlier calls. The delegate that uses the saved data is basically Task.FromResult(myDocArray) . Whether fresh or cached, I have more code that is going to process the document objects.) (我这样做是为了随意从服务器获取新数据,或使用从较早的调用中缓存的已保存数据。使用已保存数据的委托基本上是Task.FromResult(myDocArray) 。或缓存,我有更多代码将用于处理document对象。)

The main question is, if I call the async version, can I await the return value's property? 主要问题是,如果我调用异步版本,是否可以等待返回值的属性? If so, how? 如果是这样,怎么办? If not, do I have to wait for the result to get the property (as in, response.Result )? 如果不是,我是否必须等待结果获取属性(例如, response.Result )?

(Simplified) code sample: Call the sync method, but wrap in a task. (简体)代码示例:调用sync方法,但包装一个任务。 This seems like it would work fine, and is what I would do if there wasn't an async version of the getDocs method. 这似乎可以正常工作,并且如果没有getDocs方法的异步版本,那将是我的工作。

Func<Task<document[]>> f = async () => {
    var docs = Task.Run(() => service.GetDocs());
    return await docs;
}

(Simplified) code sample: Call the async version, but then ... ? (简体)代码示例:调用异步版本,但是然后...?

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);
}

Both versions appear to work fine, but in this case, the async route seems awkward. 两种版本都可以正常工作,但是在这种情况下,异步路由似乎很尴尬。 Is there a better way to handle such a case? 有没有更好的方法来处理这种情况?

Thanks! 谢谢!

Do not use .Result on task you did not await as it in most cases lead to deadlock ( await vs Task.Wait - Deadlock? , await works but calling task.Result hangs/deadlocks ) 不要在未await任务上使用.Result ,因为在大多数情况下,它会导致死锁( await与Task.Wait-Deadlock?await有效,但调用task.Result挂起/死锁

I think you want to just return documents from your async delegate: 我认为您只想从异步委托中返回documents

Func<Task<document[]>> f = async () => {
    Task<getDocsResponse> task = service.GetDocsAsync();
    getDocsResponse response = await task;
    return response.documents;
}

Note that result of the async method is always Task<> of whatever type you return . 请注意,异步方法的结果始终是您return的任何类型的Task<> You don't need to wrap result in Task.FromResult . 您不需要将结果包装在Task.FromResult

FromResult is useful when you need to match Task<T> signature but have only synchronous method. 当您需要匹配Task<T>签名但只有同步方法时, FromResult很有用。 So synchronous call you have may be rewritten synchronously (unless you really need async code, but generally it is not recommended practice - What is the best way for wrapping synchronous code into asynchronous method ) 因此,您可能需要同步重写同步调用(除非您确实需要异步代码,但是通常不建议这样做- 将同步代码包装为异步方法的最佳方法是什么

Func<Task<document[]>> f = () => Task.FromResult(service.GetDocs());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM