使用 Backgroundworker 和 byte[] 在后台下载文件

Downloading Files in Background with Backgroundworker and byte[]

我想使用 Backgroundworker 从网络服务器下载一些文件。我已经有了这个

WebClient req = new WebClient();

byte[] pbo = request.DownloadData(PathOnWebserver);
FileStream dwn = File.Create(LocalPath);
dwn.Write(pbo, 0, pbo.Length);
dwn.Close();`

在我的第一次尝试中,运行在 WindowsForm 应用程序中成功。 现在我 运行 在 Wpf 应用程序中使用了相同的代码,它抛出了 OutOfMemoryException。 所以我用谷歌搜索了这个问题,但在下载完整文件之前我没有找到存储数据的解决方案。 我需要这个,因为稍后我必须处理这个文件,如果我有损坏的数据,比如如果我关闭应用程序,我可以将它们扔进垃圾桶。

是否有一种简单的方法来获得类似于 运行 的代码,以保证数据完整?

使用 Task Parallel Library (TPL) 提供的 Task class 可能会更幸运。下面是一个可能的解决方案的简短模型。您显然需要实例化下载数据时使用的变量,例如 LocalPathPathOnWebserver.

// Call this method to start the download
private void DownloadData()
{
    // Create a TaskFactory on the current Thread; the UI thread
    TaskFactory UITaskFactory = 
        new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());

    // Create and start a Task that will download the data
    var DoDownloadTake = Task.Factory.StartNew(() =>
    {
        Boolean success = false;
        try
        {
            WebClient wc = new WebClient();
            byte[] pbo = wc.DownloadData(PathOnWebserver);
            FileStream dwn = File.Create(LocalPath);
            dwn.Write(pbo, 0, pbo.Length);
            dwn.Close();
            success = true;
        }
        catch(Exception ex){} // Handles this however you'd like to.

        // Call a method on the UI thread to notify us the download completed
        UITaskFactory.StartNew(() => DataFinishedDownloading(success));
    });
}

// Once the data is finished downloading this method will be called
private void DataFinishedDownloading(Boolean success)
{
    if(success)
        ;// Do something with data at LocalPath
    else
        ;// Download failed
}

就这样

req.DownloadFile(PathOnWebserver, TempLocalPath); 
File.Move(TempLocalPath, LocalPath);

如果 TempLocalPath 与 LocalPath 在同一驱动器上,则 Move 是原子的,因为它只是执行重命名。如果您遇到故障,您只需在启动时将临时文件丢弃即可。 Chrome 和 Firefox 等程序通过在文件仍在下载时将 .partial 添加到文件名来执行此确切方法,然后在完成后重命名。