使用任务时出现意外的线程中止异常。为什么?

2024-03-22

我有一个在应用程序域中运行的控制台应用程序。应用程序域由自定义 Windows 服务启动。该应用程序使用父任务来启动多个有效的子任务。当计时器寻找新工作时,在任何给定时间都可能有许多父任务和子任务一起运行。

所有父任务的句柄位于任务列表中:

 static List<Task> _Tasks = new List<Task>();

当管理员更改 xml 配置文件时(或当调用服务关闭时),Windows 服务能够通过将字符串令牌放入应用程序域插槽中来向正在运行的应用程序发送停止信号。该应用程序在计时器上运行,并检查槽中是否有要关闭的信号,然后尝试通过等待所有任务结束来优雅地结束其正在执行的操作。

任务的启动方式如下:

Task parent = Task.Factory.StartNew(() =>
            {
                foreach (var invoiceList in exportBucket)
                {
                    KeyValuePair<string, List<InvoiceInfo>> invoices = new KeyValuePair<string, List<InvoiceInfo>>();
                    invoices = invoiceList;
                    string taskName = invoices.Key; //file name of input file
                    Task<bool> task = Task.Factory.StartNew<bool>(state => ExportDriver(invoices),
                        taskName, TaskCreationOptions.AttachedToParent);
                }
            });
            _Tasks.Add(parent);

自定义 GAC dll 包含一个执行该工作的类。 GAC 功能中没有共享对象。 GAC 类在每个子任务中实例化:

Export export = new Export();

每个子任务在执行过程中的某个时刻都会调用一个方法:

foreach (var searchResultList in SearchResults)
{
      foreach (var item in searchResultList)
      {
          if (item.Documents.Count > 0)
          {
              //TODO: this is where we get thread issue if telling service to stop
              var exported = export.Execute(searchResultList);
              totalDocuments += exported.ExportedDocuments.Count();
          }
      }
 }

searchResultList不在任务之间共享。当应用程序运行时,export.Execute 对所有子任务按预期执行。当在应用程序中检测到停止信号时,它会尝试等待所有子任务结束。我尝试了几种方法来等待每个父项下的子任务结束:

foreach (var task in _Tasks){task.Wait();}

and

while (_Tasks.Count(t => t.IsCompleted) != _Tasks.Count){}

当等待代码执行时,会发生线程异常:

Error in Export.Execute() method: System.Threading.ThreadAbortException: Thead was being aborted at WFT.CommonExport.Export.Execute(ICollection '1 searchResults)

我不想使用取消令牌,因为我希望任务完成,而不是取消。

我不清楚为什么 GAC 类方法不高兴,因为每个任务都应该有一个唯一的方法对象句柄。

UPDATE:

感谢您的评论。只是为了进一步澄清这里发生的事情......

理论上,等待子任务的方法不应该有任何理由:

while (_Tasks.Count(t => t.IsCompleted) != _Tasks.Count){}

不应该工作,但

Task.WaitAll()

这当然是一个更好的方法,并有助于充实问题。经过进一步测试后发现,问题之一是当应用程序域应用程序告诉调用服务时,没有通过填充服务读取的槽来完成任何工作:

AppDomain.CurrentDomain.SetData("Status", "Not Exporting");

应用程序中该语句在代码中的时间和位置是错误的。作为多线程新手,我花了一段时间才发现当我发出命令时任务仍在运行SetData至“不导出”。因此,当该服务认为可以关闭并拆除应用程序域时,我相信这导致了ThreadAbortException。从那时起我就搬走了SetData声明到更可靠的位置。


回答您的问题:您收到线程中止,因为任务是在“后台”线程上执行的。

应用程序终止前不会等待后台线程. See 这个 MSDN 链接 http://msdn.microsoft.com/en-us/library/h339syd0(v=vs.71).aspx以获得进一步的解释。

现在为了尝试帮助解决您的实际问题,我建议Task.WaitAll()Jim 提到的方法,但是您应该更稳健地处理应用程序终止。我怀疑,当您在关闭之前等待任务完成时,您不会阻止新任务排队。

我建议使用退出阻塞信号量,并且排队任务的系统会在初始化时增加该信号量,并在处置时减少该信号量。

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

使用任务时出现意外的线程中止异常。为什么? 的相关文章

随机推荐

  • 存储 ASP.NET 密钥、密码的安全方法

    存储网站密钥和 或密码的最佳实践是什么 这些密钥用于各种第 3 方 Web 服务 最好将它们放在 Web config 文件中 数据库中或以某种方式加密吗 您可以将加密值存储在 config 文件中 ASP NET 2 0 将即时解密它们
  • 如何查看我的 Redis 数据库 current_size?

    我知道 redis cli 以及 info 和 config 命令 但是 他们没有任何说明当前数据库大小的信息 我怎样才能弄清楚这一点 使用INFO命令 完整详细信息在这里 http redis io commands info http
  • VSCode 1.14.0 7月更新有重大问题:如何回滚?

    因此 新的 VSCode 更新版本 1 14 0 会导致以下主要问题 CPU 使用率高 导致冻结 随机崩溃 扩展不可用 IntelliSense 工作一半时间 所以我的问题是如何将 VSCode 回滚到以前的版本而不丢失我的配置 1 14
  • 如何测试放置在子文件夹中的 django 应用程序?

    我在测试分组在子文件夹中的 django 应用程序时遇到问题 好吧 让我解释一下情况 标准 django 项目结构如下所示 django project appname1 appname2 appname3 lib tests docs s
  • 将 NSColor 转换为 RGB

    我正在尝试将 NSColor 转换为 RGB 但它似乎给出了完全错误的结果 NSColor testColor NSColor colorWithCalibratedWhite 0 65 alpha 1 0 const CGFloat co
  • 输入类型提交与输入类型按钮

    我一直在尝试用 PHP 解决一个恼人的行为 我认为 也许你们中的一些人也遇到过同样的情况并有一些想法 我有一个 html 表单 并且使用一个带有 onClick 事件的元素来调用 javascript 函数 处理脚本的内容后 我执行 for
  • 可以更换大开关吗?

    我有一个名为 ReportController aspx 的页面 其目的是根据查询字符串参数实例化报告 类 switch Request QueryString Report case ReportA CreateReportAReport
  • Matplotlib rcparams (autolimit_mode) 用于单个图形

    我对新的 Matplotlib 2 0 0 有疑问 默认情况下 新的 autolimit mode 值会向框架添加填充 我想避免它变成一个数字 如果我更改 rcParams 则更改会影响任何生成的图形 我可以更改单个图形的此参数而不影响其余
  • 通过公式而不是脚本在单元格中使用 Google Sheets 文件名?

    有没有FORMULA这将在单元格中显示文件的名称 我找到了可以做到这一点的脚本 可以显示工作表名称的公式 但没有找到可以显示文件名的公式 如果我必须诉诸剧本 那就这样吧 但如果可能的话我想使用公式 如果以前有人问过这个问题 请指出该帖子 我
  • Object.values() 的替代版本

    我正在寻找替代版本Object values 功能 As 此处描述 https developer mozilla org en US docs Web JavaScript Reference Global Objects Object
  • 以数组形式遍历不平衡二叉树

    不平衡 或非堆 二叉树可以使用数组表示 如下所示 array 1 2 null 3 4 5 6 null 7 8 null 1 2 null 3 4 5 6 null 7 8 null 如何使用给定的数组进行树遍历 更具体地说 如何计算父母
  • 如何在颤振中的当前位置创建圆圈

    我正在开发 flutter 项目 我必须在谷歌地图上的当前位置上画一个圆圈 有人知道吗 我想要这样的颤振 提前致谢 此功能现已在 google maps flutter 包中提供 https pub dev documentation go
  • 使用facet_wrap和geom_segment删除不必要的y轴点

    我使用以下命令将 y 轴点映射到 x 轴geom segment 然后使用facet wrap将数据分成两个图 然而 y 轴点都显示在这两个图上 我怎样才能只拥有与每个相关的必要的 y 轴点facet wrap 示例代码 dat lt st
  • 无法调整图表边距

    我创建了一个图表 但它在 Y 轴和图表边框之间有一个左边距 我怎样才能让它变成0 是否可以在图表和边框之间定义 5px 的统一边距 左 上 右 下 我的图表代码如下 Chart chart new Chart AntiAliasing An
  • 使用 ObjectInputStream 读取文件时出现 EOFException [重复]

    这个问题在这里已经有答案了 我基本上有一个类似的问题 如此处所述 Java中读取objectinputstream时出现EOF异常 https stackoverflow com q 2308128 1065197 但我找不到干净代码的答案
  • jQuery 1.4.1 中缺少 JSON stringify?

    显然 jQuery 能够将给定的对象或字符串解码为 JSON 对象 但是 我有一个 JS 对象 需要将其 POST 回服务器 并且我在 jQuery 中找不到包装 JSON stringify 函数的实用程序 Chrome Safari 4
  • 在运行时改变对象的行为

    如何在运行时更改对象的行为 使用C 我举一个简单的例子 我有课Operator包含一个方法operate 让我们假设它看起来像这样 double operate double a double b return 0 0 用户将给出一些输入值
  • ASP.NET MVC 模型与表单元素名称中的破折号绑定

    我一直在互联网上搜索 试图找到一种方法 将表单元素中的破折号容纳到 MVC 2 3 甚至 4 中 ASP NET 控制器的默认模型绑定行为中 作为一名前端开发人员 我更喜欢 CSS 中的破折号 而不是驼峰命名法或下划线 在我的标记中 我想要
  • 客户无需离开您的网站即可使用 Paypal 进行付款

    我的客户给我这个链接https www paypal com webapps mpp compare business products https www paypal com webapps mpp compare business p
  • 使用任务时出现意外的线程中止异常。为什么?

    我有一个在应用程序域中运行的控制台应用程序 应用程序域由自定义 Windows 服务启动 该应用程序使用父任务来启动多个有效的子任务 当计时器寻找新工作时 在任何给定时间都可能有许多父任务和子任务一起运行 所有父任务的句柄位于任务列表中 s