martinoss
martinoss

Reputation: 5458

TPL Problems, Error-Handling and Return Values

I'm trying for hours to implement a scenario like this, but with input parameters and a return value.

This works fine and I get what I expect:

public class AsyncStuff2
{
    public void DoAsyncStuff()
    {            
        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task myTask = Task.Factory.StartNew(() =>
        {
            OperationXy();
        });

        bool hadError = false;

        myTask = myTask.ContinueWith(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }
        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

       myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done");

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);

    }

    private void OperationXy()
    {
        Console.WriteLine("OperationXY");
        throw new ArgumentException("Just for Test");
    }

Output will be this:

OperationXY Faulted One or more errors occurred. Done ...but with error

But when I modify this example, task continuation does not work as i except anymore:

public class AsyncStuff
{

    public string Path { get; set; }

    public void DoAsyncStuff()
    {
        Path = "A Input...";

        TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        Task<string> myTask = Task<string>.Factory.StartNew((input) =>
        {
            return OperationXy(Path);

        }, Path, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);

        bool hadError = false;

        myTask = myTask.ContinueWith<string>(errorTest =>
        {
            Console.WriteLine("Faulted");
            hadError = true;

            if (errorTest.Exception != null)
            {
                Console.WriteLine(errorTest.Exception.Message);
            }

            return null;

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiScheduler);

        myTask.ContinueWith(another =>
        {
            Console.WriteLine("Done, Result: {0}", myTask.Result);

            if (hadError)
            {
                Console.WriteLine("...but with error");
            }

        }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, uiScheduler);
    }

    private string OperationXy(string returnThat)
    {
        Console.WriteLine("OperationXY, Input ({0})", returnThat);

        //throw new ArgumentException("Just for Test");

        return returnThat;
    }

}

What I want to achieve is:

Any help appreciated

Thanks

Martin

Upvotes: 0

Views: 923

Answers (1)

Ade Miller
Ade Miller

Reputation: 13733

This is because your code has a bug in it. You redefine myTask in your creation of the error handling continuation. The line:

        myTask = myTask.ContinueWith(errorTest =>

Should read:

        myTask.ContinueWith(errorTest =>

Otherwise you are adding the ran to completion continuation to the error handling continuation, not to the original myTask.

This should fix your code. The output should now read:

OperationXY 
Done

Upvotes: 1

Related Questions