我正在构建一个将文件上传到Google Drive的应用程序.当我绑定属性并标记它们时,它崩溃并显示以下错误:

System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))'

我的代码->

MyFiles类:

propfull Progress<IUploadProgress> progress;
propfull double Value;
propfull string Name;
propfull double Size;
propfull string fullpath;

//each one of properties has `OnPropertyChanged()` in SET
//More properties...

public virtual void OnPropertyChange([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    Debug.WriteLine($"~~~~~~{propertyName} invoked!");
}

public MyFiles(StorageFile file)
{
    FileInfo fileInfo = new FileInfo(file.Path);
    this.fullpath = file.Path
    this.Size = fileInfo.Length;
    this.Value = 0;
    this.Name = file.name;
    this.progress = new Progress<IUploadProgress>();
    this.progress += progressChanged; //prog.Report() is calling this
}

private void progressChanged(object sender, IUploadProgress e)
{
    if (e.Status == UploadStatus.Uploading)
    {
        this.Value = (e.BytesSent * 100) / this.Size; 
        //invoke(this.value) property.
        //Binding to ProgressBar.Value
    }
}

MediaPage.xaml文件:

<ListView x:Name="myListView" Grid.Row="1" Grid.Column="1" Height="600" Width="700">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid Height="70">
                <StackPanel Orientation="Horizontal">
                    <Grid>
                        <TextBlock Text="{Binding Name}" VerticalAlignment="Center" Margin="10,20" FontSize="20"  Grid.Row="0" FontFamily="Yu Gothic UI Semibold"/>
                        <ProgressBar Value="{Binding Value}" Tag="{Binding Name}" Height="5" Width="200"/>
                    </Grid>
                </StackPanel>
            </Grid>

        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
<Button x:Name="upload_btn" Click="ButtonClick" Height="40" Width="150" Content="Upload All Files"/>

MediaPage.xaml.cs中的代码

public MediaPage()
{
    this.InitializeComponent();
    SavedData.files = new ObservableCollection<MyFiles>();
    StorageFile file = ...; // testing file
    SavedData.files.Add(new MyFiles(file));

    myListView.ItemsSource = SavedData.files;
}

private void ButtonClick(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < SavedData.files.Count; i++)
    {
        DriveClass.UploadFile(i, SavedData.files[i].progress); //(index,progress)
    }
}


DriveClass代码:

public void UploadFile(int index, IProgress<IUploadProgress> prog)
{

    try
    {
        StorageFile file = StorageFile.GetFileFromPathAsync([SavedData.files[index].fullpath).AsTask().Result;

        var fileMetadata = new Google.Apis.Drive.v3.Data.File()
        {
            Name = Path.GetFileName(file.Name),
            MimeType = "application/octet-stream"
            
        };

        using (var stream = file.OpenStreamForReadAsync().Result)
        {
            

            var request = this.drive.Files.Create(fileMetadata, stream, "application/octet-stream");

            request.ProgressChanged += (IUploadProgress progressInfo) =>
            {
                if (progressInfo.Status == UploadStatus.Completed)
                {
                    Debug.WriteLine($"done!");
                    prog.Report(progressInfo);
                }
                else if (progressInfo.Status == UploadStatus.Failed)
                {
                    Debug.WriteLine($"Failed To Upload Into Google Drive");
                    prog.Report(progressInfo);
                }
                else
                {
                    Debug.WriteLine(progressInfo.BytesSent + " has sent");
                    prog.Report(progressInfo);

                }
            };

            request.ChunkSize = 262144;
            request.Upload();

            var uploadedFile = request.ResponseBody;
            Debug.WriteLine($"File uploaded: {uploadedFile.Name} ({uploadedFile.Id})");

        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Cant uplaod the file because -> " + ex.Message);
    }
}

这就是整个卡德.一切正常,直到我按下按钮并拨打UploadFile().

UploadFile()中,当quest.Progress sChanged处于活动状态时,它调用files[i].progress.ProgressChanged().

ProgressChanged()正在更新files[i].Valueinvoke()以更改ProgressBar.Value = "{Binding Value}"

应用程序在Invoke()行崩溃,因为我无法更新用户界面.

推荐答案

经过搜索,我发现了一些有用的东西.

调用UI连接到的属性的方法是将此类Dispatcher添加到OnPropertyChanged().

public async virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    });

}

在添加这Dispatcher之后,代码仍在运行,但应用程序被卡住了.因此,我将UploadFile()改为Task,而不是void,并将以下代码添加到MediaPage.xaml.cs中的ButtonClick()事件

Task UploadFileTask = Task.Run(() => DriveClass.UploadFile(index,progress));

这也将继续上传进度.

Here how the ProgressBar looks and what I wanted to do

我在this question中看到了答案.

Csharp相关问答推荐

当打印一行x个项目时,如何打印最后一行项目?

在依赖性注入和继承之间进行 Select

. net依赖注入如何避免服务类中的新

如何注册接口类型,类型<>

如何在C#中使用正则表达式抓取用逗号分隔的两个单词?

从应用程序图API调用访问所有者字段

不带身份的Blazor服务器.Net 8 Cookie身份验证

Int和uint相乘得到LONG?

有没有办法使.NET 6应用程序在特定的.NET 6运行时版本上运行

在C#中,有没有一种方法可以集中定义跨多个方法使用的XML参数描述符?

System.Text.Json .NET 8多形态语法化

如何让两个.NET版本不兼容的项目对话?

为什么我不能从我的异步任务方法中返回异步任务方法?

MudBlazor Textfield已禁用,但其验证工作正常

类/值和日期的泛型方法

无效的Zip文件-Zip存档

ASP.NET核心MVC|如何在控制器方法之间传递值

客户端/服务器RPC如何处理全局变量?

无法将.Net Framework 4.8.1升级到.Net 7

C#If条件格式