Where to define callback for Task based asynchronous method

49,650

The generally accepted way is 3.

Users of TPL generally know that they can continue a Task with ContinueWith. 1 and 2 provide the same functionality, but with a non-standard interface; the user has to figure out what the delegate parameter means and what to pass e.g. if they don't want to continue -- all that while the method still returns a Task that can be continued in the standard way.

Share:
49,650
GazTheDestroyer
Author by

GazTheDestroyer

Updated on February 18, 2020

Comments

  • GazTheDestroyer
    GazTheDestroyer about 4 years

    Following this question, I am trying to implement an async method using the TPL, and trying to follow TAP guidelines.

    I want my async method to perform a callback when it's finished. As far as I can see there are three ways I can do this.

    1) Callback manually in my task delegate

    public Task DoWorkAsync(DoWorkCompletedCallback completedCallback)
    {
        return Task.Factory.StartNew(
        { 
            //do work
    
            //call callback manually
            completedCallback();
        });
    }
    

    2) Assign callback to task in task delegate

    public Task DoWorkAsync(DoWorkCompletedCallback completedCallback)
    {
        return Task.Factory.StartNew(
        { 
            //do work
        }
        ).ContinueWith(completedCallback); //assign callback to Task
    }
    

    3) Assign callback to task in caller

    public Task DoWorkAsync()
    {
        return Task.Factory.StartNew(
        { 
            //do work
        });
    }
    
    public void SomeClientCode()
    {
        Task doingWork = DoWorkAsync();
        doingWork.ContinueWith(OnWorkCompleted);
    }
    

    My gut feeling is that 3 is more correct, because it decouples the callback from the method, and means that client code can manage the task any way it sees fit (using callbacks, polling etc), which seems to be what Tasks are all about. However, what happens if DoWorkAsync() completes its work before the client code hooks up its callback?

    Is there a generally accepted way to do this or is it all too new?

    Is there any advantage of doing 2) over 1)?

  • GazTheDestroyer
    GazTheDestroyer over 12 years
    Thanks, that makes sense. Will go with 3. But what happens if the task completes before the continue delegate is attached? Does it still get called? I'm finding the docs a bit vague.
  • Patrick Schmidt
    Patrick Schmidt about 11 years
    I have a question to example 3. If SomeClientCode() is running on the ui thread (WPF), will OnWorkCompleted also be on the ui thread? Or the same thread which did the async work?
  • GazTheDestroyer
    GazTheDestroyer about 11 years
    @PatrickSchmidt: The TPL makes no assumption or guarantees about which thread a task will run on. It depends on the scheduler used. Having said that, it won't be the ui thread since that could be anywhere at the point of DoWorkAsync() completes.
  • Adarsh Kumar
    Adarsh Kumar about 10 years
    How to join main thread and continue if I have multiple Tasks.