有一个下载文件的代码,在较低级别有一个简单的循环,限制了多次下载尝试,它看起来像这样简化:
private static bool Failed = false;
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (o, a) => { throw a.Exception; };
ChapterDownload().Wait();
}
public static async Task ChapterDownload()
{
try
{
var pages = Enumerable.Range(0, 20);
var pTasks = pages.Select(page =>
{
return PageDownload()
.ContinueWith(t => Console.WriteLine("{0}{1}", t.Status, t.IsFaulted));
});
await Task.WhenAll(pTasks.ToArray());
}
catch (Exception ex)
{
//
}
}
public static async Task PageDownload()
{
if (Failed)
throw new Exception("boom");
try
{
// var file = await new WebClient().DownloadDataTaskAsync(new Uri(@"http://example.com"));
var file = await DownloadFile(new Uri(@"http://example.com"));
if (file != null)
throw new Exception("Restart download, downloaded file is corrupted");
}
catch (Exception ex)
{
Failed = true;
await PageDownload();
}
}
public static async Task<byte[]> DownloadFile(Uri uri)
{
byte[] result;
WebResponse response;
var request = WebRequest.Create(uri);
try
{
response = await request.GetResponseAsync();
using (var memory = new MemoryStream())
{
await response.GetResponseStream().CopyToAsync(memory);
result = memory.ToArray();
}
}
catch (System.Exception ex)
{
return null;
}
if (response.ContentLength == result.LongLength)
return result;
return null;
}
问题是 - 在当前形式下,它发生UnobservedTaskException在 textboom上,即 显然是我的。同时,如果我将自制下载替换为webclient-UnobservedTaskException它不再发生。有什么区别?
为了使任务异常 (
Task) 被视为已处理并且不会导致事件TaskScheduler.UnobservedTaskException,必须重新抛出它们,例如t.Result, ,t.Wait()或t.GetAwaiter().GetResult(), 或通过访问Exception:属性查看t.Exception。在您的代码中,出现问题是因为您等待的不是原始任务本身的完成,而是它们的延续。虽然延续不会处理原始任务的异常。因此,原始任务中发生的异常仍未处理。