Task return value, without Task<T> (async/await pattern)
You can't.
The entire point of async
is to run code asynchronously. So the code returns a promise of a future string
value, represented in .NET as Task<string>
.
Think about it this way: if your code calls public string GetSomeValue()
, then by the time the method returns, you already have a string
. This is synchronous, by definition.
In your example, you have "heavy" work which I interpret to mean "CPU-bound". In that case, just do the work synchronously:
public string DoSomeHeavyWork()
{
// do some long working progress and return a string
return "Hello World!";
}
In general, APIs should not "lie"; if they are synchronous, then they should have a synchronous (non-Task
-returning) signature.
Edit: As per your comment, the "heavy" work is a WCF call, which is I/O-bound, not CPU-bound.
In that case, the work is naturally asynchronous. Use asynchronous WCF methods (not Task.Run
), and allow the asynchrony to grow through your codebase:
public async Task<string> GetSomeValueAsync()
{
//directly return the value of the Method 'DoSomeHeavyWork'...
var t = DoSomeHeavyWorkAsync();
return await t;
}
public async Task<string> DoSomeHeavyWorkAsync()
{
// Call asynchronous WCF client.
await ...;
return "Hello World!";
}
Rand Random
Updated on June 08, 2022Comments
-
Rand Random almost 2 years
I would like to write the following:
public string GetSomeValue() { //directly return the value of the Method 'DoSomeHeavyWork'... var t = DoSomeHeavyWork(); return t.Result; } public Task<string> DoSomeHeavyWork() { return Task.Run(() => { // do some long working progress and return a string return "Hello World!"; }); }
As you can see to return the result from the
DoSomeHeavyWork()
I have used the Task.Result property, which works okay, but according to researches this will block the Thread.I would like to use the async/await pattern for this but cant seem to find how to do this. If I did the same with async/await with my current knowledge I will always end up with this:
public async Task<string> GetSomeValue() { //directly return the value of the Method 'DoSomeHeavyWork'... var t = DoSomeHeavyWork(); return await t; } public Task<string> DoSomeHeavyWork() { return Task.Run(() => { // do some long working progress and return a string return "Hello World!"; }); }
This solution doesnt quite fit my needs because I want to return ONLY the string and not a
Task<string>
, how can this be achieved with async/await? -
Rand Random almost 10 yearsHow would you solve my problem, with the
Task.Result
property or do you know of anything better? (Would be happy about code snippets if you know a better alternative) -
Rand Random almost 10 yearsIn my real live example I am calling a WCF request to a client, and wanted to have a method thats running async to not block the client while server is calling the method (both Server/Client are WPF) should I than return the Task object instead of the resolved string/object?
-
Stephen Cleary almost 10 yearsI've edited my answer with my preferred solution: just do the work directly. And I've edited it again since the "heavy" work is a WCF request.
-
Rand Random almost 10 yearsSo its no issue if the WCF client implements the following interface:
[OperationContract()] Task<string> GetAccountValue(string accNr, string propertyName);
instead of a simple string/object? -
Stephen Cleary almost 10 yearsRight; anything
Task
-returning is asynchronous, and if you consume it asynchronously (viaawait
), it all works. -
Rand Random almost 10 yearsI just had fear that a task object cannot be a return value of a wcf method cause of serialization. Gonna try it on Monday, will come back to accept if every thing runs smoothly.
-
Stephen Cleary almost 10 yearsIf it does try to serialize the task, that's a sign that WCF is out of date; as long as you're on .NET 4.5, WCF should recognize that
Task<T>
is just an asynchronous way of sayingT
.