简体   繁体   中英

How to ensure callbacks of parent tasks has been completed in child task

internal int SomeFunction()
{
    Task<AddResult> task1 = new Task<AddResult>(() => AddFunction());
    task1.Start();            
    Task<FuncResult> task2 = task1.ContinueWith(task => func1(task1.Result), TaskContinuationOptions.OnlyOnRanToCompletion);       
    Task task3 = task2.ContinueWith(task => func2(task2.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
    Task task4 = task3.ContinueWith(task => func3(task2.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
    return 200;
} 

void callback(byte response) {

}

in above func1 and func2 functions will send some data to a device and response will be received in callback function. func3 will save data into database but before that i need to ensure that all the callbacks are completed. how can i achieve this.

Make use of Task.WhenAll() and store your individual tasks in a collection.

List<Task<t>> _tasks = new List<Task<t>>();

// Now add your tasks...
_tasks.Add(Task<DeviceInfo>(() => AddNodeToNetwork((Modes)mode)));
// Next task, etc.

Finally await for all tasks. This will run the awaiter on the calling thread.

await Task.WhenAll(_tasks);

This will run the awaiter from the a thread pool thread.

await Task.WhenAll(_tasks).ConfigureAwait(false);

I think the trick is to refer to the parameter called 'task' in your lambda expressions. This is the task you're following on from, so if you refer to 'task' rather than 'task1', 'task2', 'task3' etc, then by asking for task.Result , you guarantee that the previous task has been executed.

The only other thing is that you will need to wait for task4 (the final one) to complete, which you could do with a call to Task.WaitAll(new [] { task4 })

internal int SomeFunction()
{
    Task<AddNodeResult> task1 = new Task<DeviceInfo>(() => AddNodeToNetwork());
    task1.Start();            
    Task<ZWNode> task2 = task1.ContinueWith(task => GetCommandClassesVersions(task.Result), TaskContinuationOptions.OnlyOnRanToCompletion);       
    Task task3 = task2.ContinueWith(task => GetManufacturerSpecific(task.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
    Task task4 = task3.ContinueWith(task => PersistAddedNode(task.Result), TaskContinuationOptions.OnlyOnRanToCompletion);
    return 200;
}     

Apologies if this doesn't compile -- just typing in a text editor here!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM