10

For example, the difference between this code

public Task<IList<NewsSentimentIndexes>> GetNewsSentimentIndexes(DateTime @from,
    DateTime to = new DateTime(), string grouping = "1h")
{
    var result = _conf.BasePath
        .AppendPathSegment("news-sentiment-indexes")
        .SetQueryParams(new
        {
            from = from.ToString("s"),
            to = to.ToString("s"),
            grouping
        });

    return result
       .GetStringAsync()
       .ContinueWith(Desereialize<IList<NewsSentimentIndexes>>);
}

and that

public async Task<IList<NewsSentimentIndexes>> GetNewsSentimentIndexes(DateTime @from,
    DateTime to = new DateTime(), string grouping = "1h")
{
    var result = _conf.BasePath
        .AppendPathSegment("news-sentiment-indexes")
        .SetQueryParams(new
        {
            from = from.ToString("s"),
            to = to.ToString("s"),
            grouping
        });

    var newsStr =  await result.GetStringAsync();
    return JsonConvert.DeserializeObject<NewsSentimentIndexes>(newsStr);
}

Which one is correct or faster working? And just call this method need to await or just a task?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Gleb Patcia
  • 365
  • 2
  • 15

3 Answers3

7

The async one is better. You should always prefer to use await instead of ContinueWith. I go into the details of why ContinueWith is bad on my blog.

The semantic differences between these two implementations are due to two differences: whether or not async is used, and whether or not ContinueWith is used.

Removing async changes exception semantics. When async is used, any exceptions are caught (by the compiler-generated state machine) and placed on the returned task. Without async, exceptions are raised directly (synchronously). So, if BasePath, AppendPathSegment, SetQueryParams, or GetStringAsync throw (or return null or anything like that), then that exception would be raised synchronously rather than asynchronously, which could be confusing to callers.

Using ContinueWith changes execution semantics. In this case, Deserialize will be scheduled on TaskScheduler.Current. This dependence on the current TaskScheduler is one of the trickiest parts of ContinueWith.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Tell me please how to be a WaitAll and their continuation . It 's impossible to use the await – Gleb Patcia Jun 19 '16 at 14:56
  • `Task.WaitAll( _newsService.GetAll(DateTime.Now.AddYears(-1), to: DateTime.Now) .ContinueWith(ContinuationAction), _tradingPairService.GetAllExchangeTradingPairAsync(ExchangeId, TradingPairId).ContinueWith(ContinuationAction), _companyTypesService.GetAll().ContinueWith(ContinuationAction) );` – Gleb Patcia Jun 19 '16 at 14:57
  • I read your blog thank you, but you have to WaitAll example, with the same tasks. With the continuation of the same – Gleb Patcia Jun 19 '16 at 15:03
  • 2
    @GlebPatcia: In this case you should use `WhenAll` and not `WaitAll`. You can always use `await` instead of `ContinueWith`. Sometimes you just need to introduce a new method. Like `async Task GetAndProcessAsync(...) { await _newsService.GetAll(..); ContinuationAction(); }` which can then be used as `await Task.WhenAll(GetAndProcessAsync(..), ..);` – Stephen Cleary Jun 19 '16 at 16:14
  • Thank you! now I understand – Gleb Patcia Jun 19 '16 at 16:32
5

Both methods returns same type: Task. But async method allows to use await keyword in his body. It informs compiler to generate state machine for await and its all. About async/await performance you can read this post

Kirill
  • 7,580
  • 6
  • 44
  • 95
-3

Async Task returns the object, while Task does not.

So you can do this with Async Task:

var yourTask = AsyncTask()

while you can do this with normal Task:

NormalTask().someFunction()