Hi @Daniel Lee , Welcome to Microsoft Q&A,
Asynchronous operations in the loop are performed through await DownloadFileAsync, which may cause the UI thread to block. You can try using Task.Run to move the asynchronous operation to a background thread for execution, and then perform UI updates on the UI thread.
private async void button1_ClickAsync(object sender, EventArgs e)
{
// Start the Marquee animation
StartStopMarquee(true);
var downloadFileUrl = "https://onlinetestcase.com/wp-content/uploads/2023/06/25-MB.wmv";
destinationFolderPath = Path.GetFullPath(@"C:\xxx");
int numberOfDownloads = 200;
await Task.Run(async () =>
{
for (int i = 1; i <= numberOfDownloads; i++)
{
string destinationFilePath = Path.Combine(destinationFolderPath, $"file_{i}.wmv");
using (HttpClient client = new HttpClient())
{
string url = downloadFileUrl;
// Move the declaration inside the loop
int downloadNumber = i;
var progress = new Progress<DownloadProgress>(dp => ReportProgress(dp.Percent, downloadNumber, dp.ExpectedSize, stopwatch.Elapsed, dp.TotalBytesRead));
// Offload the download operation to a separate thread
await DownloadFileAsync(client, url, destinationFilePath, progress, downloadNumber);
}
}
});
}
Moreover, the update of label1 is performed in BeginInvoke, which puts the update operation on the UI thread. However, the ReportProgress method is called on each iteration in the loop, which frequently updates the UI.
Frequent UI updates can cause lags, especially when doing a lot of asynchronous operations in a loop. Each call to ReportProgress will trigger a UI update, which may cause the UI thread to block, resulting in lags.
async Task DownloadFileAsync(HttpClient client, string url, string destination, IProgress<DownloadProgress> progress, int downloadNumber)
{
stopwatch = Stopwatch.StartNew();
await Task.Run(async () =>
{
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
using (var stream = await response.Content.ReadAsStreamAsync())
using (var fileStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
{
var buffer = new byte[8192];
long totalRead = 0;
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await fileStream.WriteAsync(buffer, 0, bytesRead);
totalRead += bytesRead;
// Report progress
var downloadProgress = new DownloadProgress
{
Percent = (int)((double)totalRead / response.Content.Headers.ContentLength.Value * 100),
DownloadNumber = downloadNumber,
ExpectedSize = response.Content.Headers.ContentLength.Value,
TotalBytesRead = totalRead
};
// Update UI on the main thread
BeginInvoke(new Action(() => progress.Report(downloadProgress)));
}
}
// Raise the DownloadCompleted event when the download is successful
DownloadCompleted?.Invoke(this, new DownloadEventArgs(downloadNumber, destination));
}
});
}
This modification uses BeginInvoke to marshal the UI update to the main thread.
Best Regards,
Jiale
If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.