在 BackgroundWorker 中等待下载完成
Wait for download to complete in 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();
}
你可以使用类似这样的东西,它使用 "wait and pulse" 机制来延迟代码,直到你的下载操作完成:
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);
}
但是,如果您有资源,我建议重构您的代码以完全使用异步等待方法(从而避免后台工作者)。后台工作者是传统的异步方法之一,而推荐的方法是 TAP.
有关如何执行此操作的示例,请参阅 Stephen Cleary 的回答。
您可以使用同步 WebClient
方法(例如,DownloadFile
而不是 DownloadFileTaskAsync
),或者您可以只使用 async
/await
直接 而不是 BackgroundWorker
的 。在这种情况下,您主要做的是 I/O,因此 async
比 BackgroundWorker
.
更合适
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();
}
我有一个带进度条的对话框。显示对话框时,后台工作者应下载两个文件(使用 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();
}
你可以使用类似这样的东西,它使用 "wait and pulse" 机制来延迟代码,直到你的下载操作完成:
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);
}
但是,如果您有资源,我建议重构您的代码以完全使用异步等待方法(从而避免后台工作者)。后台工作者是传统的异步方法之一,而推荐的方法是 TAP.
有关如何执行此操作的示例,请参阅 Stephen Cleary 的回答。
您可以使用同步 WebClient
方法(例如,DownloadFile
而不是 DownloadFileTaskAsync
),或者您可以只使用 async
/await
直接 而不是 BackgroundWorker
的 。在这种情况下,您主要做的是 I/O,因此 async
比 BackgroundWorker
.
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();
}