Reputation: 2076
I have a Dialog with a progressbar. A Backgroundworker should download two files (with the WebClient) and copy them to a specified location automatically, when the Dialog is shown. How can I wait for the files to be downloaded before copying the new files.
I have tried to do something with await
, but I cant change the Backgroundworker to a async method. How can I wait in the worker for the download to complete?
Code to run the 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();
}
Code in DoWork handler (paths are not empty in actual code):
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();
}
Upvotes: 3
Views: 1459
Reputation: 456917
You can either use the synchronous WebClient
methods (e.g., DownloadFile
instead of DownloadFileTaskAsync
), or you can just use async
/await
directly instead of BackgroundWorker
. In this case, you're doing mainly I/O, so async
is a better fit than BackgroundWorker
.
An async
solution would look something like this:
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();
}
Upvotes: 2
Reputation: 35318
You can use something like this, which uses a "wait and pulse" mechanism to delay the code until your download operation has completed:
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);
}
However, if you have the resources, I'd suggest refactoring your code to entirely use an async-await approach (thus obviating the background worker). The background worker is one of the legacy asynchronous approaches while the recommended approach is TAP.
See Stephen Cleary's answer for an example of how to do this.
Upvotes: 1