WPF异步上传Google云存储进度条不更新问题求助
解决WPF中Google Cloud Storage上传进度不更新ProgressBar的问题
首先,问题的核心原因是:WPF的UI控件只能在UI线程中更新,而Google Cloud Storage上传的进度回调是在后台线程触发的,直接在回调里修改ProgressBar.Value会因为线程不匹配而失效(虽然不会报错,但UI不会更新)。
下面是具体的修复步骤和代码示例:
1. 完善上传方法,添加进度监听
你需要使用ObjectsResource.InsertMediaUpload类来处理上传,它内置了进度回调事件。修改你的上传方法,加入进度回调,并通过WPF的Dispatcher切换到UI线程更新ProgressBar:
// 假设你的WPF窗口里有一个名为uploadProgressBar的ProgressBar控件 private async Task<bool> UploadToGoogleCloudStorage(string bucketName, string token, string filePath, string contentType) { // 初始化Storage服务(确保已完成服务账号认证) var storageService = new StorageService(new BaseClientService.Initializer { HttpClientInitializer = /* 你的服务账号认证对象,比如ServiceAccountCredential */, ApplicationName = "你的应用名称" }); var fileInfo = new FileInfo(filePath); var newObject = new Google.Apis.Storage.v1.Data.Object() { Bucket = bucketName, Name = Path.GetFileName(filePath), // 设置上传后的文件名 ContentType = contentType }; // 创建上传请求,并设置进度回调 using (var fileStream = new FileStream(filePath, FileMode.Open)) { var uploadRequest = storageService.Objects.Insert(newObject, bucketName, fileStream, contentType); uploadRequest.ChunkSize = ResumableUpload.MinimumChunkSize; // 可选:设置分块大小 // 绑定进度变化事件 uploadRequest.ProgressChanged += (sender, args) => { // 计算上传进度百分比 double progressPercentage = (args.BytesSent * 100.0) / fileInfo.Length; // 控制台输出进度(你原来的逻辑) Console.WriteLine($"已发送:{args.BytesSent} / 总大小:{fileInfo.Length}"); // 关键:使用Dispatcher切换到UI线程更新ProgressBar uploadProgressBar.Dispatcher.Invoke(() => { uploadProgressBar.Value = progressPercentage; }); }; // 执行上传 var result = await uploadRequest.UploadAsync(); return result.Status == UploadStatus.Completed; } }
2. 关键注意点
- Dispatcher的使用:
Dispatcher.Invoke会将更新UI的代码调度到UI线程执行,这是WPF中跨线程更新UI的标准方式。如果代码在ViewModel中(比如MVVM模式),可以通过Application.Current.Dispatcher获取全局Dispatcher。 - 进度计算:通过
args.BytesSent(已发送字节数)除以文件总长度得到百分比,刚好匹配ProgressBar默认的Minimum=0、Maximum=100的设置。 - 认证配置:确保服务账号认证已正确完成,比如通过
ServiceAccountCredential.FromServiceAccountFile加载密钥文件,这是上传的前提。
3. MVVM模式下的处理(可选)
如果使用MVVM不直接操作UI控件,可通过绑定ViewModel属性实现:
在ViewModel中定义带通知的进度属性:
private double _uploadProgress; public double UploadProgress { get => _uploadProgress; set { _uploadProgress = value; OnPropertyChanged(); } } // 实现INotifyPropertyChanged接口的方法 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
进度回调中更新ViewModel属性:
uploadRequest.ProgressChanged += (sender, args) => { double progressPercentage = (args.BytesSent * 100.0) / fileInfo.Length; Application.Current.Dispatcher.Invoke(() => { UploadProgress = progressPercentage; }); };
XAML中绑定:
<ProgressBar Value="{Binding UploadProgress}" Minimum="0" Maximum="100" Height="20"/>
这样就能保证进度条正确响应上传进度了。
内容的提问来源于stack exchange,提问作者kempyyyy
相关产品推荐
相关产品推荐

