gpt4 book ai didi

c# - 使用 WebClient.DownloadFileAsync 时如何处理异常

转载 作者:太空狗 更新时间:2023-10-29 22:58:20 25 4
gpt4 key购买 nike

我正在使用 WebClient 按以下方式从 Internet 下载一些文件:

try  
{
ManualResetEvent mr = new ManualResetEvent(false);
mr.Reset();
using (WebClient wc = new WebClient())
{
wc.DownloadFileCompleted += ((sender, args) =>
{
if (args.Error == null)
{
File.Move(filePath, Path.ChangeExtension(filePath, ".jpg"));
mr.Set();
}
else
{
//how to pass args.Error?
}
});
wc.DownloadFileAsync(new Uri(string.Format("{0}/{1}", Settings1.Default.WebPhotosLocation, Path.GetFileName(f.FullName))), filePath);
mr.WaitOne();
}
}
catch (Exception ex)
{
//Catch my error here and handle it (display message box)
}

但我似乎无法将错误从我的匿名 DownloadFileCompleted 方法传递到我的主要捕获。执行此操作的正确方法是什么?

最佳答案

重新抛出的错误解决方案

您可以将异常保存在 lambda 外部定义的某个变量中。然后它可以被重新抛出:

Exception exc = null;
using (WebClient wc = new WebClient())
{
wc.DownloadFileCompleted += ((sender, args) =>
...

mr.WaitOne();

if (exception != null) throw exception;
}

为什么不好?因为您将丢失堆栈跟踪(它将显示异常是在当前方法中抛出的,而不是在 WebClient 中抛出的)。尽管如此,如果您不需要或不关心堆栈跟踪,这也是可能的解决方案。

就地处理异常

您也可以只创建一些方法来处理外部 try-catch 和下载的处理程序中的异常:

void HandleWebClientException(Exception exc)
{
...
}

try
{
ManualResetEvent mr = new ManualResetEvent(false);
mr.Reset();
using (WebClient wc = new WebClient())
{
wc.DownloadFileCompleted += ((sender, args) =>
{
if (args.Error == null)
{
File.Move(filePath, Path.ChangeExtension(filePath, ".jpg"));
mr.Set();
}
else
{
HandleWebClientException(args.Error);
}
});
wc.DownloadFileAsync(new Uri(string.Format("{0}/{1}", Settings1.Default.WebPhotosLocation, Path.GetFileName(f.FullName))), filePath);
mr.WaitOne();
}
}
catch (Exception ex)
{
HandleWebClientException(ex);
}

做对了

最好的办法是避免在 WebClient 上使用 void 方法,因为你不能 await在他们身上或应用一些 continuation .

这些方法在某种意义上很方便,但它们迫使您使用具有同步结构的 secret 解决方案,以减少工作流对不同回调的依赖。

要使用异步等待,您必须申请 public Task<byte[]> DownloadDataTaskAsync(Uri address) 方法。

您可以:

1. await它获取数据的字节数组以便稍后手动保存它,但它需要在您的应用程序中进行可靠的返工才能使其成为 async all the way :

public async Task LoadFile()
{
try
{
using (WebClient wc = new WebClient())
{
var bytes = await wc.DownloadDataTaskAsync(new Uri(string.Format("{0}/{1}", Settings1.Default.WebPhotosLocation, Path.GetFileName(f.FullName))), filePath);
System.IO.File.WriteAllBytes(bytes); // Probably turn it into async too
}
}
catch (Exception ex)
{
//Catch my error here and handle it (display message box)
}
}

它会起作用,但我不确定 DownloadDataTaskAsync是真正的异步方法。

2. 所以你也可以考虑使用Task Continuations用同样的方法:

public Task LoadFile()
{
Task<Byte[]> bytesTask = wc.DownloadDataTaskAsync(new Uri(string.Format("{0}/{1}", Settings1.Default.WebPhotosLocation, Path.GetFileName(f.FullName))), filePath);

var success = bytesTask.ContinueWith((prev) =>
{
System.IO.File.WriteAllBytes(prev.Result);
},
TaskContinuationOptions.OnlyOnRanToCompletion);


var failure = bytesTask.ContinueWith(prev =>
{
MessageBox.Show //...
},
TaskContinuationOptions.OnlyOnFaulted);

return Task.WhenAny(success, failure);
}

P.S.: 为什么不使用简单的屏蔽方法 public void DownloadFile(Uri address, string fileName) 如果您不需要异步加载文件?

关于c# - 使用 WebClient.DownloadFileAsync 时如何处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30534704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com