【发布时间】:2014-03-26 17:43:36
【问题描述】:
我已经设计并制作了一个原型应用程序,用于作为 Windows 服务 (C#) 运行的高性能、多线程邮件合并。这个问题是指问题的一个棘手部分,如果进程挂在数据库调用上该怎么办。我对此进行了很多研究。我已经阅读了很多关于线程取消的文章,但我最终只看到了一种方法,thread.Abort()。是的,我知道,绝对不要使用 Thread.Abort(),所以几天来我一直在研究如何以另一种方式进行操作,并且在我看来,别无选择。我会告诉你为什么,希望你能告诉我为什么我错了。
仅供参考,这些都是长时间运行的线程,因此 TPL 无论如何都会将它们置于 ThreadPool 之外。
TPL 只是线程的一个很好的包装器,所以我绝对没有看到任务可以做任何线程不能做的事情。只是做的不一样。
使用线程,您有两种选择来停止它。 1. 在处理循环中让线程轮询以查看是否有标志请求取消,然后结束处理并让线程死亡。没问题。 2.调用Thread.Abort()(然后捕捉异常,做一个Join,担心Finally等)
这是线程中的数据库调用,所以一旦启动轮询将不起作用。
另一方面,如果您使用 TPL 和 CancellationToken,在我看来您仍在轮询然后创建异常。它看起来就像我在案例 1 中用线程描述的一样。一旦我开始该数据库调用(我还打算在它周围放置一个异步/等待),我就无法测试 CancellationToken 中的更改。就此而言,TPL 更糟糕,因为在 Db 读取期间调用 CancellationToken 将完全不执行任何操作,远不如 Thread.Abort() 执行的操作。
我不敢相信这是一个独特的问题,但我还没有找到真正的解决方案,我已经阅读了很多。无论是线程还是任务,工作线程都必须轮询以知道它应该停止然后停止(连接到 Db 时不可能。它不在循环中。)否则线程必须中止,抛出 ThreadAbortedException 或 TaskCanceledException .
我目前的计划是将每个作业作为一个长时间运行的线程启动。如果线程超过时间限制,我会调用Thread.Abort,在线程中捕获异常,然后在Abort()之后的线程上做Join()。
我非常非常愿意接受建议...谢谢,迈克
我会放这个链接,因为它声称可以这样做,但我无法弄清楚它并且没有回复让我认为它会起作用 multi-threading-cross-class-cancellation-with-tpl
哦,这看起来很有可能,但我也不知道Treating a Thread as a Service
【问题讨论】:
-
如果数据库驱动程序可以接受
CancellationToken,那么它可能能够监听它并优雅地取消请求。例如,在 SQL Management Studio 中,您可以取消正在运行的请求,因此 ADO.Net 驱动程序可以做到这一点并非不可能。它是否真的这样做是另一回事。如果你Thread.Abort()则它会抛出一个不可停止的异常,因此在这种情况下驱动程序可能会或可能不会取消。
标签: c# .net multithreading