Ответ 1
Большинство методов Task
-returning предназначены для использования с async
/await
(и как таковой не должны использовать Task.Run
или Task.Factory.StartNew
внутренне).
Обратите внимание, что при обычном способе вызова асинхронных методов не имеет значения, как генерируется исключение:
await CheckWebPageAsync();
Разница возникает только тогда, когда метод вызывается и затем ожидается позже:
List<Task> tasks = ...;
tasks.Add(CheckWebPagesAsync());
...
await Task.WhenAll(tasks);
Однако, как правило, вызов (CheckWebPagesAsync()
) и await
находятся в одном блоке кода, поэтому они все равно будут в одном и том же блоке try
/catch
, и в этом случае он также ( обычно) не имеет значения.
существует ли стандартное/соглашение, которое ограничивает поведение задачи вторым вариантом?
Нет стандарта. Предпосылки - это тип головокружения исключение, поэтому на самом деле не имеет значения, как он был брошен, потому что он никогда не должен быть пойман в любом случае.
Джон Скотт считает, что предпосылки должны быть выбрасываны напрямую ( "вне" возвращенной задачи):Task CheckWebPageAsync(string url) {
if(url == null) // argument check
throw Exception("Bad url");
return CheckWebPageInternalAsync(url);
}
private async Task CheckWebPageInternalAsync(string url) {
if((await PageDownloader.GetPageContentAsync(url)).Contains("error"))
throw Exception("Error on the page");
}
Это обеспечивает неплохую параллель с операторами LINQ, которые гарантированно выдают исключения "раньше" (вне списка).
Но я не думаю, что это необходимо. Я считаю, что код проще при метании предусловий внутри задачи:
async Task CheckWebPageAsync(string url) {
if(url == null) // argument check
throw Exception("Bad url");
if((await PageDownloader.GetPageContentAsync(url)).Contains("error"))
throw Exception("Error on the page");
}
Помните, что никогда не будет никакого кода, который ловит предварительные условия, поэтому в реальном мире не должно различаться, как генерируется исключение.
С другой стороны, это один момент, когда я фактически не согласен с Джоном Скитом. Таким образом, ваш пробег может меняться... много.:)