我用文件流传输1G以上大小的大文件,传输过程不用Application.DoEvents(),如何让界面不卡死,用的winform,用await和async还是会卡
引用 皆我百晓生 小程序回复内容作答:
在传输大文件时,为了保证界面不会卡死,可以考虑使用异步操作。在C#中,可以使用async
和await
关键字来实现异步操作。
以下是一个示例的代码:
private async Task TransferFileAsync(string sourceFilePath, string destinationFilePath)
{
using (FileStream sourceFileStream = new FileStream(sourceFilePath, FileMode.Open))
using (FileStream destinationFileStream = new FileStream(destinationFilePath, FileMode.Create))
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = await sourceFileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await destinationFileStream.WriteAsync(buffer, 0, bytesRead);
// 更新UI进度条等界面操作可以放在这里
}
}
}
在调用该方法时,可以使用await
来等待传输完成:
await TransferFileAsync(sourceFilePath, destinationFilePath);
通过使用异步操作,传输大文件的过程将会在后台线程进行,而不会阻塞主线程,从而保证界面的响应性。
注意,你还可以在传输过程中,使用事件或委托进行进度更新等界面操作,而不需要使用Application.DoEvents()
。
上传文件跟“Application.DoEvents()”没有必然联系
除非你想带进度,或者跟着某园子写成一个“while(true)” 一次写1024字节。
如果是上传文件还想带进度,建议用“IProcess” 进行进度通知
分析完毕,我也不想写代码,直接问chartgpt好了
“C# httpclient 异步上传文件 使用IProcess 在UI上实时显示进度”
chartgpt的回答(我不保证chartgpt 代码正确,只是告诉你我们的思路以及最后可能的代码实现)
public async Task UploadFileWithProgressAsync(string filePath, Uri uploadUri, IProgress<double> progress)
{
var progressHandler = new ProgressMessageHandler();
// Subscribe to the progress event
progressHandler.HttpSendProgress += (sender, args) =>
{
if (args.TotalBytes == 0) return; // To avoid division by zero
double percentComplete = (double)args.BytesTransferred / args.TotalBytes * 100.0;
progress.Report(percentComplete);
};
using (var httpClient = new HttpClient(progressHandler))
using (var fileStream = File.OpenRead(filePath))
using (var content = new MultipartFormDataContent())
{
var fileContent = new StreamContent(fileStream);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = Path.GetFileName(filePath)
};
content.Add(fileContent);
var response = await httpClient.PostAsync(uploadUri, content);
// Handle the response as needed
}
}
调用层
var progress = new Progress<double>(percent => {
//注意这里可能有跨进程操作,如何处理你自己来,你是invoke,还是用上下文同步,你看情况弄
progressBar.Value = percent;
});
await UploadFileWithProgressAsync("path_to_file", yourUploadUri, progress);
发现是任务里用了同步模型里的上下文造成了卡顿