You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:01:42