При использовании задач для больших/длительных рабочих нагрузок, которые мне нужно отменить, я часто использую шаблон, подобный этому для действия, выполняемого задачей:
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
Log.Exception(ex);
throw;
}
}
Исключение OperationCanceledException не должно регистрироваться как ошибка, но не должно быть проглочено, если задача заключается в переходе в отмененное состояние. Любые другие исключения не должны рассматриваться в рамках этого метода.
Это всегда казалось немного неуклюжим, и визуальная студия по умолчанию разрывает бросок для OperationCanceledException (хотя у меня есть "break on User-unhandled", отключенный теперь для OperationCanceledException из-за моего использования этого шаблона).
В идеале я думаю, что хотел бы сделать что-то вроде этого:
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (Exception ex) exclude (OperationCanceledException)
{
Log.Exception(ex);
throw;
}
}
то есть. имеют какой-то список исключений, применяемый к catch, но без поддержки языка, который в настоящее время невозможен (@eric-lippert: С# vNext:)).
Другим способом будет продолжение:
public void StartWork()
{
Task.Factory.StartNew(() => DoWork(cancellationSource.Token), cancellationSource.Token)
.ContinueWith(t => Log.Exception(t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
public void DoWork(CancellationToken cancelToken)
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
но мне это не очень нравится, так как исключение технически может иметь больше одного внутреннего исключения и у вас не так много контекста при регистрации исключения, как в первом примере (если бы я делал больше, чем просто зарегистрировав его).
Я понимаю, что это немного вопрос стиля, но интересно, есть ли у кого-нибудь лучшие предложения?
Мне просто нужно придерживаться примера 1?
Эамон