C# wpfui冻结

C# wpfui冻结,c#,wpf,user-interface,C#,Wpf,User Interface,我正在尝试更新UI上的2个标签和2个进度条。 但是它不工作,表单只是冻结,在保存结束之前不会发生任何事情。 在windows窗体中,我习惯于使用Invoke并使其更新。如何在WPF中实现更新 谢谢 public void EncryptFiles(string saveFileLocation, string saveFileTitle, string saveFileExtension) { using (ZipFile zip = new ZipFile()) {

我正在尝试更新UI上的2个标签和2个进度条。 但是它不工作,表单只是冻结,在保存结束之前不会发生任何事情。 在windows窗体中,我习惯于使用Invoke并使其更新。如何在WPF中实现更新

谢谢

public void EncryptFiles(string saveFileLocation, string saveFileTitle, string saveFileExtension)
{

    using (ZipFile zip = new ZipFile())
    {


        zip.Password = passwordField1.Password;
        zip.Encryption = EncryptionAlgorithm.WinZipAes256;
        foreach (File file in dataStorage.listOfFiles)
        {

            zip.AddFile(file.fileLocation, String.Empty);
        }
        zip.SaveProgress += SaveProgress;


        zip.Save(System.IO.Path.Combine(saveFileLocation, saveFileTitle + saveFileExtension));

    }

}


public void SaveProgress(object sender, SaveProgressEventArgs e)
{
    if (e.EventType == ZipProgressEventType.Saving_Started)
    {
        System.Windows.Forms.MessageBox.Show("Begin Saving: " + e.ArchiveName);
    }
    else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
    {

        labelCompressionStatus.Content = "Writing: " + e.CurrentEntry.FileName + " (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
        labelFilename.Content= "Filename:" + e.CurrentEntry.FileName;
        progressBar2.Maximum = e.EntriesTotal;
        progressBar2.Value = e.EntriesSaved + 1;


    }
    else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
    {
        progressBar1.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer);  
    }
    else if (e.EventType == ZipProgressEventType.Saving_Completed)
    {
        System.Windows.Forms.MessageBox.Show("Done: " + e.ArchiveName);
    }
}

除非在单独的线程中执行代码,否则在完成方法之前,UI不会更新。更改progressBar1的值不会有任何影响,因为在所有工作完成之前,更改不会可见。最简单的方法可能是将加密文件的工作分配给BackgroundWorker:

BackgroundWorker bw = new BackgroundWorker() { WorkerReportsProgress = true };
bw.DoWork += EncryptFiles;
bw.ProgressChanged += ReportEncryptSaveProgress;
然后,保持对bw的引用,并在每次更新任务时调用bw.ReportProgress,将完成百分比传递给该方法。假设ReportProgress发生在UI线程上,您应该将您的更新放在其中的ProgressBar中,用户应该可以看到保存的进度

请注意,我不能100%确定您希望如何将工作转移到BackgroundWorker中-我不能肯定我知道ZipFile对象的事件是如何工作的,因此您可能需要稍微处理一下它。考虑到我假设您不能更改SaveProgress的方法签名,将BackgroundWorker作为类的字段可能比将其传递给SaveProgress更容易


您可以使用Dispatcher来完成UI更新,但在整个操作过程中,您的UI仍然会完全锁定,这通常是可以避免的。

除非您在单独的线程中执行代码,否则在完成方法之前,UI不会更新。更改progressBar1的值不会有任何影响,因为在所有工作完成之前,更改不会可见。最简单的方法可能是将加密文件的工作分配给BackgroundWorker:

BackgroundWorker bw = new BackgroundWorker() { WorkerReportsProgress = true };
bw.DoWork += EncryptFiles;
bw.ProgressChanged += ReportEncryptSaveProgress;
然后,保持对bw的引用,并在每次更新任务时调用bw.ReportProgress,将完成百分比传递给该方法。假设ReportProgress发生在UI线程上,您应该将您的更新放在其中的ProgressBar中,用户应该可以看到保存的进度

请注意,我不能100%确定您希望如何将工作转移到BackgroundWorker中-我不能肯定我知道ZipFile对象的事件是如何工作的,因此您可能需要稍微处理一下它。考虑到我假设您不能更改SaveProgress的方法签名,将BackgroundWorker作为类的字段可能比将其传递给SaveProgress更容易

您可以使用Dispatcher完成UI更新,但您的UI在整个操作过程中仍然会被完全锁定,这通常是可以避免的。

编辑:我的答案仅适用于在与UI线程不同的线程上运行解压缩操作的情况,而UI线程不必是后台工作线程。否则,弗克尔的答案就是你想要的

查看WPF。它是针对这种使用情况设计的,大致类似于Winforms中的Control.Invoke。

编辑:我的答案仅适用于在不同于UI线程的线程上运行解压缩操作的情况,而不必是后台工作线程。否则,弗克尔的答案就是你想要的

Dispatcher.Invoke(new Action(() => { 
 // code here for updating GUI
 }), DispatcherPriority.ContextIdle);
查看WPF。它是为这个用例设计的,大致类似于Winforms中的Control.Invoke

Dispatcher.Invoke(new Action(() => { 
 // code here for updating GUI
 }), DispatcherPriority.ContextIdle);
找到这个,它对我有用,谢谢大家


找到了这个,它对我很有用,谢谢大家。请将ProgressBar任务放到工作线程上,如本示例所述:此答案可能有用将ProgressBar任务放到工作线程上,如本示例所述:此答案可能有用啊,你是对的。我认为他已经在一个单独的线程上运行这个,因为他说他在WinForms中做过类似的事情。@Xcelled194这是我的一个假设,但他似乎在另一个线程上。否则我想他会问关于InvalidCrossThreadAccess的问题,而不是为什么他的UI什么都不做。也许他得到了那个错误并解决了它?虽然我不知道没有调度员你怎么解决。。。我想我们得等着看手术怎么说。啊,你说得对。我认为他已经在一个单独的线程上运行这个,因为他说他在WinForms中做过类似的事情。@Xcelled194这是我的一个假设,但他似乎在另一个线程上。否则我想他会问关于InvalidCrossThreadAccess的问题,而不是为什么他的UI什么都不做。也许他得到了那个错误并解决了它?虽然我不知道没有调度员你怎么解决。。。我想我们必须等待,看看OP会说些什么。如果这对你有效,你应该接受Xcelled194的回答——他在将近半小时前告诉你这么做。再加上背景工作者,这对我有效。谢谢如果这对你有效,你应该接受Xcelled194的回答——他让你做了将近半个小时
你以前做过。再加上背景工作者,这对我来说很有效。谢谢