在后台进程中访问 WPF FlowDocument

2024-05-20

在后台访问 WPF FlowDocument

我的问题涉及在 WPF 后台访问 UI 对象。我见过几十个示例应用程序,它们都很简单、易于理解,其中 95% 告诉你如何显示进度条。这并不是我想要的......

我的问题是这样的:我想通过访问 RichTextBox 中的 FlowDocument 来执行一项长任务(或许多长任务)。确切的任务与这里无关,但一个例子可能是扫描文档,并计算特定单词出现的次数,或者有多少个红色字符……。在一个很长的文档中,这些任务可能相当耗时,如果在前台完成,将会极大地占用 UI 并使其无响应。我只想解析 FlowDocument;我不想对其进行任何更改。

这就是我正在尝试做的事情。显而易见的解决方案是在后台执行此操作,但问题是……如何执行?我已经取得了什么成就appears作为一个答案,但它对我来说“感觉不对”,这就是我来这里寻求帮助的原因。

我的“解决方案”

我接下来的“解决方案”使用了一个BackgroundWorker,它调用UI对象的Dispatcher来确保访问正确的线程......并且它“看起来”可以完成这项工作。但真的吗?............ 我已经大大简化了我的“解决方案”,以便(我希望)能够轻松地遵循我正在做的事情......

WithEvents worker As BackgroundWorker
Private Delegate Sub DelegateSub()
Private theDocument As FlowDocument

''' <summary>
''' Triggers the background task. Can call from anywhere in main code blocks
''' </summary>
Private Sub StartTheBackgroundTask()

    worker = New BackgroundWorker
    worker.RunWorkerAsync()

End Sub

''' <summary>
''' In the background, hands the job over to the UI object's Dispatcher
''' </summary>
Private Sub HandleWorkerDoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles worker.DoWork

    Dim priority As System.Windows.Threading.DispatcherPriority
    Dim theLongRunningTask As DelegateSub

    '(1) Define a delegate for the Dispatcher to work with
    theLongRunningTask = New DelegateSub(AddressOf DoTheTimeConsumingTask)

    '(2) Set Dispatcher priority as required
    priority = System.Windows.Threading.DispatcherPriority.Background

    '(3) Add the job to the FlowDocument's Dispatcher's tasks
    theDocument.Dispatcher.BeginInvoke(theLongRunningTask, priority)

End Sub

''' <summary>
''' Sub whose logic accesses, but does not change, the UI object
'''  </summary>
Private Sub DoTheTimeConsumingTask()

    'For example......

    For Each bl As Block In theDocument.Blocks

        '......do something

    Next

End Sub

虽然这似乎可行,但我看到的问题是,除了使用 BackgroundWorker 触发任务之外,几乎所有长时间运行的任务都是由 UI 对象的 Dispatcher 处理的。所以BackgroundWorker实际上并不做任何工作。这就是我关心的部分;如果调度员忙于完成所有工作,我看不出我如何获得任何东西

Option 2

因此,对我来说,我最好“稍微扭转一下”并将 Dispatcher 的委托设置为指向实例化并启动 BackGroundWorker 的子进程(我的想法是,Dispatcher 线程将拥有 BackGroundWorker 的子进程),这似乎更合乎逻辑。线程),并在BackgroundWorker的DoWork事件中完成所有工作。那“感觉”是对的……

所以我尝试了这个:

WithEvents worker As BackgroundWorker
Private Delegate Sub DelegateSub()
Private theDocument As FlowDocument

''' <summary>
''' Triggers the background task. Can call from anywhere in main code blocks
''' </summary>
Private Sub StartTheBackgroundTask()

    Dim priority As System.Windows.Threading.DispatcherPriority
    Dim theTask As DelegateSub

    '(1) Define a delegate for the Dispatcher to work with
    theTask = New DelegateSub(AddressOf RunWorker)

    '(2) Set Dispatcher priority as required
    priority = System.Windows.Threading.DispatcherPriority.Normal

    '(3) Add the job to the Dispatcher's tasks
    theDocument.Dispatcher.BeginInvoke(theTask, priority)

End Sub

''' <summary>
''' Creates and starts a new BackGroundWorker object
''' </summary>
Private Sub RunWorker()

    Worker = New BackgroundWorker
    Worker.RunWorkerAsync()

End Sub

''' <summary>
''' Does the long task in the DoWork event
''' </summary>
Private Sub HandleWorkerDoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles worker.DoWork

    DoTheTimeConsumingTask()

End Sub

''' <summary>
''' Sub whose logic accesses, but does not change, the UI object
'''  </summary>
Private Sub DoTheTimeConsumingTask()

    'For example......

    For Each bl As Block In theDocument.Blocks

        '......do something

    Next

End Sub

对我来说,这一切似乎更加合乎逻辑。我推测 Dispatcher 会拥有 BackgroundWorker,而后者会完成所有耗时的工作,并且一切都将在 UI 线程上进行。好吧……逻辑思维就这么多了……(对于 WPF 通常是致命的!)……事实并非如此。它会因常见的“不同线程”错误而崩溃。所以,再想一想,这个似乎是一个更优雅的解决方案,结果却是一个失败者!

我的问题如下:

  1. 我的“解决方案”到底是不是解决方案?
  2. 我哪里错了?
  3. 如何改进“解决方案”,使调度员不被长期任务束缚......这正是我试图避免的情况?

进一步的问题。请注意,我必须使用 FlowDocument 的调度程序才能完成这项工作。如果我使用 System.Windows.Threading.Dispatcher.CurrentDispatcher 代替,则不会调用 Delegate sub (DoTheTimeConsumingTask ),因此 – 出于所有意图和目的 – 什么也不会发生。有人可以解释一下为什么不可以吗?

我来找你并不是第一个停靠点。我已经尝试了几十个选项,但还没有找到任何感觉完全正确的选项(除了我的第二个选项不起作用,哈哈),所以我请求一些指导。


您面临的主要问题是FlowDocument源自于DispatcherObject,所以你必须参与它的Dispatcher来访问它。你尝试用这个东西做的所有事情都会采取将物品放入Dispatcher的工作队列并等待它开始执行它们。其中,如果Dispatcher是处理 UI 的那个,将导致您想要避免的情况:而Dispatcher正在执行您的工作项,所有剩余的鼠标点击和击键都堆积在Dispatcher的工作队列,UI将不负责任。

你从中得到什么FlowDocument成为一个DispatcherObject是当您的长时间运行的任务正在处理它时,它的内容不能改变。一旦您的任务完成,队列中的鼠标点击和击键可能会改变它,但在它运行时,它们只是积累。这实际上很重要;如果你were能够使用Dispatcher,您会遇到 UI 中的某些内容更改了的情况FlowDocument当你的任务正在运行时。那么你就会遇到通常所说的“问题”。

即使你可以克隆FlowDocument并断开克隆与 UI 调度程序的连接,它仍然是一个DispatcherObject,并且尝试同时执行多个任务时您仍然会遇到相同的问题;您可以选择序列化对它的访问或观察后台线程崩溃。

为了解决这个问题,你需要做的是制作某种非DispatcherObject的冻结快照FlowDocument。然后在快照上运行您的任务。这样,如果 UI 处于活动状态,则更改FlowDocument当您的任务运行时,它不会扰乱您的游戏。

我会做什么:使用XamlWriter并序列化FlowDocument进入一个XDocument。序列化任务涉及Dispatcher,但一旦完成,您可以根据需要对数据运行任意数量的古怪并行分析,并且 UI 中的任何内容都不会影响它。 (而且一旦它是XDocument你可以使用 XPath 来查询它,这是一个非常好的锤子,只要你的问题实际上是钉子。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在后台进程中访问 WPF FlowDocument 的相关文章

  • 为什么 IsAssignableFrom() 不适用于 int 和 double?

    这是错误的 typeof double IsAssignableFrom typeof int 这是错误的 typeof int IsAssignableFrom typeof double 但这有效 double a 1 0 int b
  • 如何查找局域网中所有主机上正在运行的程序的所有实例?

    出于实际目的 SqlDataSourceEnumerator 的作用是查找在 LAN 上的各个 PC 上运行的 SQL Server 的所有实例 是否有等效的方法可以查找任意应用程序的运行实例 编辑 好的 所以这只有效 因为这些应用程序有预
  • 字典 API(词汇)[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有人知道一个好的 NET 字典 API 吗 我对含义不感兴趣 而是我需要能够以多种不同的方式查询单词 返
  • 将 WPF 快捷键绑定到 ViewModel 中的命令

    我有一个使用 MVVM 模式的 WPF 应用程序 将按钮连接到 VM 非常简单 因为它们实现了 ICommand 我有一个工作原理类似的上下文菜单 下一步是为上下文菜单创建快捷键 我不知道如何让快捷键调用命令 这是一个例子
  • DotNET 应用程序中的 GDI 句柄

    我的纯 DotNET 库作为非托管桌面应用程序中的插件运行 我收到了稳定的 虽然低 崩溃报告流 这些报告似乎表明 GDI 句柄存在问题 错误消息中的字体等 恢复为系统字体 各种控件的显示崩溃 不久后发生大规模崩溃 我的窗体几乎没有控件 但我
  • Java有没有类似微软CHESS的工具?

    是否有类似于 Microsoft 的现有 Java 工具CHESS http research microsoft com chess 或者 CHESS 源代码是否开放 以便我可以尝试将其转换为 Java 谷歌的织线工 http code
  • 如何在Wpf中的用户控件中调用MahApps Metro对话框

    当我尝试调用 MahApps Metro 对话框时 我在传递值时遇到错误 在传递参数时调用对话框控制时我需要传递 Metrowindow 参数 但我需要在用户控件中调用它 下面是当我需要对话框控制时我将调用的方法 public async
  • EasyNetQ 模型关闭

    我使用 EasyNetQ 实现了一个简单的 RabbitMQ 客户端 连接后 我收到一条通知 队列模型关闭 这是我的代码 var bus RabbitHutch CreateBus String Format host 0 hostName
  • 列表视图上的 TextBlock:如何忽略 TextBlock 中的点击并让列表视图处理它们

    我有一个显示大量信息的列表视图 但是当它为空时 我想在其上覆盖一个文本块 上面写着 没有要显示的信息 或 bla bla bla 添加信息 列表视图设置为响应鼠标单击 但现在如果我单击文本块 这些事件将路由到文本块 我怎样才能让这些事件转到
  • 有谁知道一种更快的方法来执行 String.Split() 吗?

    我正在读取 CSV 文件的每一行 并且需要获取每一列中的各个值 所以现在我只是使用 values line Split delimiter where line是保存由分隔符分隔的值的字符串 衡量我的表现ReadNextRow我注意到它花费
  • WPF HierarchicalDataTemplate 不会在属性更改时更新 ItemsSource

    这是一些 XAML
  • 更换 I 过滤器

    我目前正在使用 IFilters 从各种文件 word excel tiff pdf 等 中提取文本 据我所知 IFilter 已在 Windows 8 中停止使用 是否有人对如何在不安装本机应用程序的情况下提取文本有任何建议 如果有什么用
  • 在 .Net 托管的 IronPython 脚本中设置和获取变量

    我正在尝试使用 Net 控制台应用程序中托管的 IronPython 来构建验证规则引擎的原型 我已经将脚本精简到我认为的基础内容 var engine Python CreateEngine engine Execute from Sys
  • 设置 Form.KeyPreview = true 的缺点?

    我想知道 Form KeyPreview 属性实际上有什么用处 它为什么存在以及将其设置为 true 会带来什么 风险 我想它一定有some负面影响 否则它根本不应该存在 或者至少默认情况下是正确的 EDIT 我很清楚what确实如此 我问
  • 使用实体框架重叠约会

    我将 asp net mvc 与实体框架一起使用 我有一个包含 startat 字段 endat 字段和 roomid 字段 称为 SpaceConfigurationId 的约会列表 并且希望查找给定房间已重复预订的约会列表 可以假设 e
  • c#.NET 和 sprintf 语法

    这段代码如何翻译成 C 具体来说是如何sprintf用C 实现 string output The user s logged in string loggedIn is string loggedOut isn t if TheUser
  • 为什么当要求修剪“PRN.NUL”时,TrimStart 会更多地修剪字符?

    这是代码 namespace TrimTest class Program static void Main string args string ToTrim PRN NUL Console WriteLine ToTrim string
  • 枚举扩展方法

    在vs2008中 是否可以编写适用于任何枚举的扩展方法 我知道您可以针对特定枚举编写扩展方法 但我希望能够使用单个扩展方法对每个枚举进行处理 这可能吗 是的 只需针对基础进行编码Enum类型 例如 public static void So
  • 引用的程序集自动由 Visual Studio 替换

    我有 2 个项目 一个可移植类库和一个常规单元测试项目 在可移植类库中 我使用 NuGet 来引用 Microsoft BCL 可移植包 它附带 2 个程序集 System Threading Tasks dll and System Ru
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码

随机推荐

  • 在 HTTP 标头中发送 UTF-8 值会导致 Mojibake

    我想使用 servlet 发送阿拉伯语数据HTTPServletResponse给客户 我正在尝试这个 response setCharacterEncoding UTF 8 response setHeader Info arabicWo
  • 带有 @RequestBody 的 Spring 多部分文件

    我正在尝试将数据从应用程序上传到 Spring 后端服务 要上传的内容是一个 DataModel 其中包含要创建的对象的数据以及链接到该数据的多个图像 因此我使用这个方法签名 RequestMapping method RequestMet
  • 如何在ASP.NET Webform中使用Jquery表单插件?

    我遇到了这个插件 http malsup com jquery form getting started http malsup com jquery form getting started 我想知道如何在 ASP NET WebForm
  • 为什么我的 Apache2::Log 输出用 \n 替换换行符?

    我在 apache2 mod perl 下设置了多个虚拟主机 我用的是ErrorLog指令为每个虚拟主机获取单独的错误日志 仅当我使用 Apache2 Log 时 这才按预期工作 警告 只会记录到常规错误日志中 这样就可以了 最后 但还存在
  • iPhone 快照,包括键盘

    我正在寻找拍摄整个 iPhone 屏幕 包括键盘 的正确方法 我找到了一些截取屏幕的代码 CGRect screenCaptureRect UIScreen mainScreen bounds UIView viewWhereYouWant
  • PrepareForSegue之谜

    我在两个不同的 VC 中有一个prepareForSegue 方法 一个使用一个if声明 而另一个旨在使用switch 除了名称之外 代码几乎相同 这个效果很好 void prepareForSegue UIStoryboardSegue
  • 如何使用 jenkins 声明性管道新语法测试 sh 脚本返回状态

    使用新的 jenkins 声明性管道语法 我想测试 sh 脚本执行的返回状态 是否可以不使用脚本步骤 脚本管道 工作 stage Check url node timeout 15 waitUntil sleep 20 def r sh s
  • 无法编译包“maps”

    当我安装 maps 包时 安装中出现警告 ld warning ignoring file Library Developer CommandLineTools SDKs MacOSX10 14 sdk usr lib libSystem
  • Android 应用被 Google Play 拒绝

    我最近向 Google Play 商店提交了一个 Android 应用程序 但收到一条消息说我的应用程序已被拒绝 我不确定问题是什么 也找不到确切的解决方案 拒绝原因 违反了禁止行为条款 内容政策 经过定期审核后 我们确定您的应用程序支持
  • 将字段中的位扩展到掩码中所有(重叠+相邻)集位的最快方法?

    假设我有 2 个名为 IN 和 MASK 的二进制输入 实际字段大小可能是 32 到 256 位 具体取决于用于完成任务的指令集 每次调用时两个输入都会改变 Inputs IN 1100010010010100 MASK 000111101
  • 将 rdfs:range 的 xsd:string 限制为 [A-Z]

    如何将数据类型属性的范围指定为文字形式与 A Z 匹配的 xsd strings OWL 限制对我来说不起作用 至少乍一看是这样 有没有办法用正则表达式来做到这一点 如果有的话 在哪里 我想你的意思是 单个大写字母 string patte
  • 有人尝试过用 C 或 C++ 为 Blackberry 平台进行开发吗?

    根据我在嵌入式计算方面的经验 我得到的每一个迹象都是 做这样的事情需要昂贵的设备才能访问平台 ICE 调试器 JTAG 探针 I2C 编程器等 但我一直想知道是否一些雄心勃勃的黑客已经找到了一种在黑莓设备上加载本机代码的方法 任何人 编辑
  • 无法在 Spring Boot 测试中模拟 persistenceContext

    我正在使用带有 Mockito 框架的 spring boot 测试来测试我的应用程序 存储库类 EntityManager 之一作为参考 我的班级如下所示 Repository Transactional Slf4j public cla
  • 如何更改服务器端口3000?

    我刚刚结束了 Angular 2 的教程 我找不到将 localhost 端口从 3000 更改为 8000 的方法 在我的package json文件中有一行 start concurrent npm run tsc w npm run
  • 为什么点击内容后放大的ajax弹出框会关闭

    请帮助我 我一直在尝试让放大的弹出ajax框显示登录表单 似乎表单出现了 但是一旦我单击表单或ajax主体中的任意位置 它就会消失 下面是代码 document ready function ajax popup link magnific
  • 使用 React.lazy 时未捕获未定义的错误

    我正在尝试实施基于路由的代码分割 https reactjs org docs code splitting html route based code splitting正如 React 文档中提到的 这是添加延迟实现之前我的应用程序 这
  • 在“FormGroup”中预填充输入字段 - Angular2

    我正在使用 Angular2 反应形式 一切正常 直到我想在表单中的字段之一中显示预填充的值 设想 页面上有多个按钮 每个按钮都会打开一个表单 其中的字段如下 Name Email Message 产品代码 gt 此值应根据服务中的每个项目
  • 在 Tensorflow tf.nn.nce_loss 中出现 TypeError:'Mul' Op 的输入 'y' 的类型为 float32,与参数 'x' 的 int32 类型不匹配

    我正在研究 Tensor Flow 中的 Bag of Words 实现 并得到了 类型错误 Mul Op 的输入 y 的类型为 float32 与参数 x 的 int32 类型不匹配 在 tf nn nce loss 中 我尝试查看 tf
  • 如何纠正这个非法字符串偏移?

    我收到此错误 警告 第 32 行 home mysite public html wp content themes evento lib php extra class php 中的非法字符串偏移 type 我意识到文件中的这部分代码是错
  • 在后台进程中访问 WPF FlowDocument

    在后台访问 WPF FlowDocument 我的问题涉及在 WPF 后台访问 UI 对象 我见过几十个示例应用程序 它们都很简单 易于理解 其中 95 告诉你如何显示进度条 这并不是我想要的 我的问题是这样的 我想通过访问 RichTex