Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining Tasks with Different Return Types

Is it possible to chain tasks with different return types or no return type at all? For example in pseudo-code:

Task<double>.ContinueWith(Task<string>).ContinueWith(Task<String>).ContinueWith(Task)

Or also here is real-code example:

private double SumRootN(int root)
{
    double result = 0;
    for (int i = 1; i < 10000000; i++)
    {
        result += Math.Exp(Math.Log(i) / root);
    }
    return result;
}

private void taskSequentialContinuationButton_Click(object sender, RoutedEventArgs e)
{
    Task<double> task = null;

    this.statusText.Text = "";
    this.watch = Stopwatch.StartNew();
    for (int i = 2; i < 20; i++)
    {
        int j = i;
        if (task == null)
        {
            task = Task<double>.Factory.StartNew(() => { return SumRootN(j); });
        }
        else
        {
            task = task.ContinueWith((t) => { return SumRootN(j); });
        }

        task = task.ContinueWith((t) => 
        { // I don't want to return anything from this task but I have to, to get it to compile
            this.statusText.Text += String.Format("root {0} : {1}\n", j, t.Result);
            return t.Result;
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }

    task.ContinueWith((t) => 
        { // I also don't want to return anything here but I don't seem to have to here even though intellisense expects a Task<double>??
            this.statusText.Text += String.Format("{0}ms elapsed\n", watch.ElapsedMilliseconds);
        }, TaskScheduler.FromCurrentSynchronizationContext());
}

See the inline comments for the oddities of the chaining.

like image 791
flolim Avatar asked Mar 11 '26 13:03

flolim


1 Answers

If you want to chain Tasks with different return types, you can just put each of them in a different variable:

Task<Type1> task1 = Task.Factory.StartNew(() => Compute1());
Task<Type2> task2 = task1.ContinueWith(_ => Compute2());
Task<Type3> task3 = task2.ContinueWith(_ => Compute3());

For your specific case, where you compute something in a loop and want to report on the UI thread after each iteration, you can do it like this:

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() =>
{
    for (int i = 2; i < 20; i++)
    {
        // perform computation

        Task.Factory.StartNew(() =>
        {
            // report result
        }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
    }
});
like image 92
svick Avatar answered Mar 14 '26 02:03

svick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!