如果返回任务的方法抛出异常? [英] Should methods that return Task throw exceptions?
问题描述
返回工作
有两种选择报告的错误方法:
Methods that return Task
have two options for reporting an error:
- 在抛出异常的时候了
- 在返回将与除了完成任务
如果主叫方希望这两种类型的错误报告,或者是有一些标准/协议限制任务行为的第二个选项?
Should the caller expect both types of error reporting or is there some standard/agreement that limits task behavior to the second option?
例如:
class PageChecker {
Task CheckWebPage(string url) {
if(url == null) // argument check
throw Exception("Bad url");
if(!HostPinger.IsHostOnline(url)) // some other synchronous check
throw Exception("Host is down");
return Task.Factory.StartNew(()=> {
// asynchronous check
if(PageDownloader.GetPageContent(url).Contains("error"))
throw Exception("Error on the page");
});
}
}
处理两种类型看起来pretty的丑陋:
Handling both types looks pretty ugly:
try {
var task = pageChecker.CheckWebPage(url);
task.ContinueWith(t =>
{
if(t.Exception!=null)
ReportBadPage(url);
});
}
catch(Exception ex) {
ReportBadPage(url);
}
使用异步/等待可能会有帮助,但有对于普通的.NET 4的解决方案,而不异步支持?
Using async/await may help, but is there a solution for plain .net 4 without async support?
推荐答案
大多数工作
-returning方法适用于具有使用异步
/ 等待
(,因此不应该使用 Task.Run
或任务.Factory.StartNew
内部)。
Most Task
-returning methods are intended for use with async
/await
(and as such should not use Task.Run
or Task.Factory.StartNew
internally).
请注意,与调用异步方法的常用的方式,它并不重要的例外是如何引发
Note that with the common way of calling asynchronous methods, it doesn't matter how the exception is thrown:
await CheckWebPageAsync();
所不同的只是来当该方法被调用,然后等待后面:
The difference only comes in when the method is called and then awaited later:
List<Task> tasks = ...;
tasks.Add(CheckWebPagesAsync());
...
await Task.WhenAll(tasks);
不过,通常是呼叫( CheckWebPagesAsync()
)和等待
在$ C的同一个块$ C,所以他们会在同一个尝试
/ 抓
反正块,而在这种情况下,它也(通常)没有关系。
However, usually the call (CheckWebPagesAsync()
) and the await
are in the same block of code, so they would be in the same try
/catch
block anyway, and in that case it also (usually) doesn't matter.
有没有一些标准/协议限制任务行为的第二个选项?
is there some standard/agreement that limits task behavior to the second option?
没有标准。 preconditions是一类愚蠢的例外的,所以它其实并不重要,它是如何抛出,因为它的不应该被抓反正。
There is no standard. Preconditions are a type of boneheaded exception, so it doesn't really matter how it's thrown because it should never be caught anyway.
乔恩斯基特是preconditions应直接抛出的观点(外返回的任务):
Jon Skeet is of the opinion that preconditions should be thrown directly ("outside" the returned task):
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运营商,这些都保证了异常的早像这样(枚举外)。
This provides a nice parallel to LINQ operators, which are guaranteed to throw exceptions "early" like this (outside the enumerator).
但我不认为这是必要的。我发现任务中抛preconditions当code是简单的:
But I don't think that's necessary. I find the code is simpler when throwing preconditions within the task:
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");
}
记住,应永远不会有任何code映入preconditions ,所以在现实世界中,应该没有任何区别的异常是如何抛出。
Remember, there should never be any code that catches preconditions, so in the real world, it shouldn't make any difference how the exception is thrown.
在另一方面,这种的是的一个点上,我居然跟乔恩斯基特不同意。所以,你的里程可能会有所不同...很多。 :)
On the other hand, this is one point where I actually disagree with Jon Skeet. So your mileage may vary... a lot. :)
这篇关于如果返回任务的方法抛出异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!