C# wpfui冻结
我正在尝试更新UI上的2个标签和2个进度条。 但是它不工作,表单只是冻结,在保存结束之前不会发生任何事情。 在windows窗体中,我习惯于使用Invoke并使其更新。如何在WPF中实现更新 谢谢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()) {
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的回答——他让你做了将近半个小时
你以前做过。再加上背景工作者,这对我来说很有效。谢谢