背景退出时的工作线程问题
本文关键字:线程 问题 工作 退出 背景 | 更新日期: 2023-09-27 18:15:33
我在这里遇到了一些难题,想知道几件事:
- 我做错了吗?
- 后台工作者在不同场景中的预期行为是什么...
- 如果可能的话,得到一个关于为什么我会得到特定行为的答案会很好......
对于第 1 点,以及最终的第 3 点,我将解释我在伪代码中所做的工作,以便您获得详细信息,而无需实际吐出数千行代码。在我写这篇文章时,我将查看代码本身,以确保信息在何时以及正在发生的事情方面是准确的。最后,我还将详细介绍正在发生的事情以及为什么我会遇到问题。
伪代码详细信息:
我有一个主 UI 线程(WinForms 窗体(,在选择几个配置选项后,单击一个按钮。
此按钮的事件在内存和文件系统上执行一些初步设置工作以启动工作,一旦完成,就会触发一个后台工作线程。此后台工作者初始化其他 5 个后台工作者(表单范围变量(,将它们的"完成"标志(bool - 相同范围(设置为 true,将其"Log"变量设置为新List<LogEntry>
(相同范围(,一旦完成,将调用一个名为 CheckEndConditions
的方法。此方法调用在初始后台辅助角色的DoWork()
内完成,而不是在RunWorkerCompleted
事件中完成。
CheckEndConditions
方法执行以下逻辑:
- 如果所有"完成"变量都设置为 True...
- 获取所有 5 个 BW 的"日志"变量,并将其内容添加到主日志中。
- 将所有 5 个 BW 的"日志"变量重置为新
List<LogEntry>
- 将所有 5 个 BW 的"完成"变量重置为 False。
- 调用
MoveToNextStep()
方法,该方法返回表示要执行的下一步的Enum
值 - 根据 (5( 的结果,获取需要处理的
List<ActionFileAction>
- 检查以确保 (6( 有要执行的操作
- 如果否,请将所有"完成"标志设置为 true,并调用自身以移动到下一步...
- 如果是,请将此操作列表划分为 5 个列表,并将它们放在名为
ThreadActionSets[]
的List<ActionFileAction>
数组中 - 检查每个分区列表的内容,如果没有,则将相应线程的"完成"标志设置为 true(这可确保没有"结束竞争场景"(
- 使用
RunWorkerAsync()
触发所有 5 个线程(当然,除非我们处于完成步骤( -
Return
每个 BW 都有完全相同的DoWork()
代码,基本上归结为以下内容:
- 我有什么操作要执行吗?
- 如果 NO,请将我的
e.Result
var 设置为日志条目的空列表并退出。 - 如果是,则循环设置中的每个操作,并在下面执行 4-5-6...
- 我在做什么行动?(组、模块等(
- 基于(4(,我在做什么类型的操作?(添加、删除、修改(
- 基于 (5(,执行正确的操作并在本地记录您所做的一切
- 完成所有操作后,将我的
e.Result
var设置为"我所做的一切日志",然后退出。
每个 BW 都有相同的RunWorkerCompleted()
代码,基本上归结为以下内容:
尝试
- 从
e.Result
var 中,获取List<LogEntry>
并将其放入我各自线程的"Log"var 中。 - 将我各自的"完成"变量设置为 true
- 呼叫
CheckEndConditions()
抓住
- 将我各自的"完成"变量设置为 true
- 呼叫
CheckEndConditions()
所以基本上就是这样...总之,我将大量操作拆分为 5 个分区,并将这些操作发送到 5 个线程,以比单个线程更快的速度执行它们。
问题所在
我遇到的问题是,无论我在比赛中花了多少心思(特别是最终场景(,我经常发现自己有一个卡住/无响应的程序。
一开始,我设置代码的效率低下,问题出在结束竞争场景中,线程完成得如此之快,以至于最后一次调用CheckEndConditions
看到其中一个"完成"变量仍然设置为 false,而实际上它不是/它已经完成......所以我将我的代码更改为您在上面看到的代码,我认为这可以解决问题,但事实并非如此。整个过程仍然卡住/进入睡眠状态,发生这种情况时实际上没有线程正在运行任何处理,这意味着最后一次调用 CheckEndConditions
时出了点问题(我认为不确定(。
所以我的第一个问题:我做错了吗?做我想做的事情的标准方法是什么?我所做的事情的逻辑对我来说感觉很合理,但它的行为并没有按照我所期望的方式进行,所以也许逻辑不合理?...
第二个问题:发生这种情况时,BW 的预期行为是什么:未捕获的DoWork()
方法中发生错误...它会触发RunWorkerCompleted()
事件吗?如果没有,会发生什么?
第三个问题:有没有人看到为什么会出现我的问题?
感谢您的帮助!
根据 OP 的要求重新发布我的评论作为答案:
RunWorkerCompleted
事件不一定会在创建它的同一线程上引发(除非它是在 UI 线程上创建的( 请参阅后台工作线程运行工作线程已完成事件
有关更多详细信息,请参阅 OP 注释。