TaskContinuationOptions.OnlyOnFaults не считается управление потоком с использованием исключений? - PullRequest
4 голосов
/ 18 августа 2011

У меня сложилось впечатление, что управление потоком с исключениями считалось плохой практикой.

Так почему бы вам сделать что-то вроде этого:

var task = Task.Factory
            .StartNew(() => command.Execute());
task.ContinueWith(t => 
                      {
                          // success callback
                      }, TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t =>
                      {
                          Log.Error(string.Format("'{0}' failed.", command.GetType()), t.Exception);
                          // error callback
                      }, TaskContinuationOptions.OnlyOnFaulted);

Когда вы могли бы так же легко catch исключение внутри command.Execute(), есть ли что-то, что я здесь упускаю? Могут ли задачи генерировать исключения, не связанные с исполняемым кодом?

EDIT : Как насчет того, чтобы использовать ключевые слова c # 5 async и await, не могли бы вы сказать, что это было бы лучше, или действительно ли ловить все не имеет значения, как в приведенном выше примере?

public class AsyncFooCommand : AsyncCommandBase<Bar>
{
    public override Bar Execute()
    {
        try
        {
            var bar = // Do something that can throw SpecificException
            Successful = true;
            return bar;
        }
        catch (SpecificException ex)
        {
            // Log
        }
    }
}
public static class AsyncCommandExecutor<T>
{
    // NOTE: don't care about sharing this between instances.
    // ReSharper disable StaticFieldInGenericType
    private static readonly ILog Log = LogManager.GetLogger(typeof(Infrastructure.Commands.AsyncCommandExecutor<>));
    // ReSharper restore StaticFieldInGenericType

    public static async Task<T> Execute(IAsyncCommand<T> command, Action<T> success = null, Action error = null)
    {

        var task = Task.Factory
            .StartNew(() =>
            {
                return command.Execute();
            });
        task.ContinueWith(t => Log.Error(string.Format("'{0}' failed, something terrible happened.", command.GetType()), t.Exception),
            TaskContinuationOptions.OnlyOnFaulted);

        T result = await task;

        if (success != null && command.Successful)
        {
            success(result);
        }
        if (error != null && !command.Successful)
        {
            error();
        }

        return result;
    }
}

1 Ответ

6 голосов
/ 18 августа 2011

Вы, конечно, могли бы и не было бы необходимости в продолжении. Это просто другой подход.

Однако, если вы поймаете исключение в задаче и оно будет выполнено до конца, для внешнего мира задача будет выглядеть успешной, а не сбойной. Если у вас есть другие продолжения, которые TaskContinuationOptions.OnlyOnRanToCompletion или другие подобные опции, и вы технически не смогли выполнить команду (и только что перехватили исключение), эта задача будет продолжаться, возможно, когда ей понадобится антецедент для успешного выполнения. Это больше об управлении состоянием задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...