Warm tip: This article is reproduced from stackoverflow.com, please click
async-await c# callback task

Where is the OnCompleted callback for Task?

发布于 2020-04-21 21:55:15

I'd like to be be able to do this:

class MyClass
{
    IRepo repo;
    public MyClass(IMyRepo repo) { this.repo = repo; }

    long ID { get; set; }
    string Prop1 { get; set; }
    string Prop2 { get; set; }

    public async Task LoadAsync()
    {
        await Task.WhenAll(
            repo.GetProp1ByIDAsync(ID).OnComplete(x => Prop1 = x),
            repo.GetProp2ByIDAsync(ID).OnComplete(x => Prop2 = x)
        );
    }
}

Of course, I can't seem to find any standard library that has this OnComplete extension for Task. Do I really need to create my own or is there a library that already has this extension method? I see that there's ContinueWith but that does not give me the unwrapped result, I still have to await it or .Result it... so wouldn't that block the thread? Holding up the second repo call until this completed? If it doesn't hold it up then why am I getting that result still wrapped, would it be cleaner to return the unwrapped result to me? Or am I missing something?

Questioner
Serj Sagan
Viewed
46
Stephen Cleary 2016-09-01 09:56

I can't seem to find any standard library that has this OnComplete extension for Task. Do I really need to create my own or is there a library that already has this extension method? I see that there's ContinueWith but that does not give me the unwrapped result, I still have to await it or .Result it... so wouldn't that block the thread?

ContinueWith is the method you're looking for; Result won't block on the task because it's already completed by the time the callback is invoked.

However, ContinueWith is a dangerous, low-level API. You should use await instead:

public async Task LoadAsync()
{
    await Task.WhenAll(
        LoadProp1Async(),
        LoadProp2Async()
    );
}

private async Task LoadProp1Async()
{
  Prop1 = await repo.GetProp1ByIDAsync(ID);
}

private async Task LoadProp2Async()
{
  Prop2 = await repo.GetProp2ByIDAsync(ID);
}