Task return value, without Task<T> (async/await pattern)

11,348

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!";
}
Share:
11,348
Rand Random
Author by

Rand Random

Updated on June 08, 2022

Comments

  • Rand Random
    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
    Rand Random almost 10 years
    How 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
    Rand Random almost 10 years
    In 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
    Stephen Cleary almost 10 years
    I'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
    Rand Random almost 10 years
    So 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
    Stephen Cleary almost 10 years
    Right; anything Task-returning is asynchronous, and if you consume it asynchronously (via await), it all works.
  • Rand Random
    Rand Random almost 10 years
    I 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
    Stephen Cleary almost 10 years
    If 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 saying T.