简体   繁体   中英

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.

getDocs() returns document[] , which is what I want.

getDocsAsync() returns Task<getDocsResponse> , where getDocsResponse has a (non-awaitable) property of type 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.)

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 )?

(Simplified) code sample: Call the sync method, but wrap in a task. This seems like it would work fine, and is what I would do if there wasn't an async version of the getDocs method.

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 )

I think you want to just return documents from your async delegate:

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 . You don't need to wrap result in Task.FromResult .

FromResult is useful when you need to match Task<T> signature but have only synchronous method. 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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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