繁体   English   中英

等待在BackgroundWorker中完成下载

[英]Wait for download to complete in BackgroundWorker

我有一个带有进度条的Dialog。 当显示对话框时,Backgroundworker应下载两个文件(使用WebClient)并自动将它们复制到指定位置。 在复制新文件之前,如何等待文件下载。

我试图做await事情,但我不能将Backgroundworker更改为异步方法。 我如何在工作人员中等待下载完成?

运行worker的代码:

private void fmUpdateingDatabaseDialog_Shown(object sender, EventArgs e)
{
    device.Connect();
    lbInformation.Text = "uploading database to " + device.FriendlyName;
    device.Disconnect();

    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.ProgressChanged += 
        new ProgressChangedEventHandler(worker_ProgressChanged);
    worker.RunWorkerCompleted += 
        new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.RunWorkerAsync();
}

DoWork处理程序中的代码(实际代码中的路径不为空):

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    //download files temporary
    WebClient client = new WebClient();
    client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
    client.DownloadFileTaskAsync(new Uri(""), Path.Combine(tempPath + ""));

    WebClient client2 = new WebClient();
    client2.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client2_DownloadProgressChanged);
    client2.DownloadFileTaskAsync(new Uri(""), Path.Combine(tempPath + ""));

    //upload files to phone
    device.Connect();
        device.TransferContentToDevice(Path.Combine(tempPath+""), folder.Id, folder, true);
        device.TransferContentToDevice(Path.Combine(tempPath+""), folder.Id, folder, true);
    device.Disconnect();
}

您可以使用同步WebClient方法(例如, DownloadFile而不是DownloadFileTaskAsync ),也可以直接使用async / await 而不是 BackgroundWorker 在这种情况下,您主要进行I / O操作,因此asyncBackgroundWorker更适合。

async解决方案看起来像这样:

private async void fmUpdateingDatabaseDialog_Shown(object sender, EventArgs e)
{
  device.Connect();
  lbInformation.Text = "uploading database to " + device.FriendlyName;
  device.Disconnect();

  var progress = new Progress<T>(data =>
  {
    // TODO: move worker_ProgressChanged code into here.
  });
  await DownloadAsync(progress);
  // TODO: move worker_RunWorkerCompleted code here.
}

private async Task DownloadAsync(IProgress<T> progress)
{
  //download files temporary
  WebClient client = new WebClient();
  client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
  await client.DownloadFileTaskAsync(new Uri(""), Path.Combine(tempPath + ""));

  WebClient client2 = new WebClient();
  client2.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client2_DownloadProgressChanged);
  await client2.DownloadFileTaskAsync(new Uri(""), Path.Combine(tempPath + ""));

  //upload files to phone
  // TODO: Check for Async versions of these methods that you can await.
  //  If there aren't any, consider using Task.Run.
  device.Connect();
  device.TransferContentToDevice(Path.Combine(tempPath+""), folder.Id, folder, true);
  device.TransferContentToDevice(Path.Combine(tempPath+""), folder.Id, folder, true);
  device.Disconnect();
}

你可以使用这样的东西,它使用“等待和脉冲”机制来延迟代码,直到你的下载操作完成:

var locker = new object(); 

Thread t = new Thread(new ThreadStart(() =>
{
    lock (locker)
    {
        //peform your downloading operation, and wait for it to finish.
        client.DownloadFileTaskAsync(new Uri(""), Path.Combine(tempPath + ""));
        while (/* not yet downloaded */) { }; 
        //inform the parent thread that the download has finished.
        Monitor.Pulse(locker);
    }
}));

t.Start();

lock(locker)
{
    Monitor.Wait(locker);
}

但是,如果你有资源,我建议重构你的代码以完全使用async-await方法(从而避免后台工作者)。 后台工作程序是传统的异步方法之一,而推荐的方法是TAP

请参阅Stephen Cleary的答案,了解如何执行此操作的示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM