Проблемы TPL, обработка ошибок и возвращаемые значения - PullRequest
0 голосов
/ 22 декабря 2010

Я часами пытаюсь реализовать такой сценарий, но с входными параметрами и возвращаемым значением.

Это отлично работает, и я получаю то, что ожидаю:

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");
    }

Вывод будет таким:

OperationXY Failed Произошла одна или несколько ошибок.Готово ... но с ошибкой

Но когда я изменяю этот пример, продолжение задачи не работает как я, кроме как:

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;
    }

}

Что я хочудостижения:

  • Передача ввода, необходимого для обработки, в задачу
  • Установить результат для элемента пользовательского интерфейса
  • Ошибка обработки, но продолжить "OnlyOnRanToCompletion""В любом случае

Любая помощь приветствуется

Спасибо

Мартин

1 Ответ

1 голос
/ 25 марта 2011

Это потому, что в вашем коде есть ошибка.Вы переопределяете myTask в своем создании продолжения обработки ошибок.Строка:

        myTask = myTask.ContinueWith(errorTest =>

должна выглядеть следующим образом:

        myTask.ContinueWith(errorTest =>

В противном случае вы добавляете продолжение выполнения к завершению к продолжению обработки ошибок, а не к исходному myTask.

Это должно исправить ваш код.Вывод должен теперь читать:

OperationXY 
Done
...