使用Thread.Abort的()和处理ThreadAbortException在.NET安全的做法?做法、安全、Abort、Thread

2023-09-02 21:12:06 作者:突然好想装逼

我需要建立在C#中的多线程的Azure工作者角色 - 创建多个线程,饲料要求对他们来说,每个请求可能需要一些很长的时间来处理(不是我的code - 我会打电话给一个COM对象做实际的工作)。

当角色关机,我需要正常停止处理。我怎么做?看起来,如果我只是叫 Thread.Abort的() ThreadAbortException 被扔在线程和线程甚至可以使用的try-catch-最后(或使用)清理资源。这看起来相当可靠。

让我困扰的是,我的经验主要是C ++,这是不可能的,正常终止线程在非托管应用程序 - 它只是停止没有任何进一步的处理,这可能会使数据不一致的状态。所以,我有点偏执这样的事情是否发生在情况下,我称之为 Thread.Abort的()对于一个繁忙的线程。

它是安全的做法是使用 Thread.Abort的()与处理 ThreadAbortException ?我应该怎么知道如果我这样做呢?

解决方案   

时使用Thread.Abort的()和处理ThreadAbortException在.NET安全技术?

TL; DR版本:不,不是。

通常你是安全的,当所有类型的不变量(无论是明确规定或不)是真的。但是在运行,只有达到一个新的状态,当他们再次在最后真正的许多方法将打破这些不变量。如果线程处于空闲状态与持有你会确定不变的状态,但在这种情况下,最好使用类似的事件信号的线程正常退出(即你不需要中止)。

带外的例外, 1 扔在一螺纹,而在这样的不变量 - 不真,即得。无效的,状态是问题的开始。这些问题包括,但当然不限于,相互不一致字段和属性值(数据结构处于无效状态),而不是退出锁,和事件重新presenting的变化发生未焙烧

在很多情况下,可以处理这些在清理code(例如,一个最后块)的但的再考虑外出时带的例外,清理code会出现什么情况?这导致清理$ C $下清理code。但随后即code是它的自我脆弱的,所以你需要清理$ C $下的清理code&hellip清理code; 它永远不会结束!的

有解决方案,但他们不容易设计(而且往往影响你的整个设计),甚至难以测试—如何重新创建所有的情况下(考虑组合的阐述)。两种可能的途径是:

Java线程池异常处理正确姿势

在国家的工作副本,更新副本,然后以原子交换当前的新状态。如果有带外的一个异常,然后原来的状态保持不变(与finalisers可以清理临时状态)。

这是有点像数据库事务的功能(尽管用的RDBMS锁和事务日志文件的工作)。

这也是类似的方法来实现强异常保证在C开发的响应的纸质疑,如果异常可能永远是安全的(当然是C ++有没有GC / finaliser队列清理丢弃的对象)。见香草Sutters 的大师周#8:挑战版:异常安全性。的解决方案。

在实践中,这是很难达到的,除非你的国家可以封装在一个单一的参考。

看约束执行区域,而不是什么限制你可以在这些情况下做的。 (MSDN杂志有一个介绍性文章(介绍对象,而不是入门级),由。 NET 2公测期间 2 )。

在实践中,如果你要做到这一点,使用方法#2来管理状态变化下的#1,可能是最好的办法,但得到它的权利,并验证它是正确的(和正确性维护)是硬盘的。

摘要:这是一个有点像优化:规则1:不要去做;第2条(专家只):不这样做,除非你有没有其他选择。

1 A ThreadAbortException 不是唯一这样的例外。

2 所以细节可能改变。

I need to develop a multithreaded Azure worker role in C# - create multiple threads, feed requests to them, each request might require some very long time to process (not my code - I'll call a COM object to do actual work).

Upon role shutdown I need to gracefully stop processing. How do I do that? Looks like if I just call Thread.Abort() the ThreadAbortException is thrown in the thread and the thread can even use try-catch-finally (or using) to clean up resources. This looks quite reliable.

What bothers me is that my experience is mostly C++ and it's impossible to gracefully abort a thread in an unmanaged application - it will just stop without any further processing and this might leave data in inconsistent state. So I'm kind of paranoid about whether anything like that happens in case I call Thread.Abort() for a busy thread.

Is it safe practice to use Thread.Abort() together with handling ThreadAbortException? What should I be aware of if I do that?

解决方案

Is using Thread.Abort() and handling ThreadAbortException in .NET safe practice?

TL;DR version: No, isn't.

Generally you're safe when all type invariants (whether explicitly stated or not) are actually true. However many methods will break these invariants while running, only to reach a new state when they are again true at the end. If the thread is idle in a state with invariants held you'll be OK, but in that case better to use something like an event to signal the thread to exit gracefully (ie. you don't need to abort).

An out-of-band exception1 thrown in a thread while in such a invariants-not-true, ie. invalid, state is where the problems start. These problems include, but are certainly not limited to, mutually inconsistent field and property values (data structures in an invalid state), locks not exited, and events representing "changes happened" not fired.

In many cases it is possible to deal with these in clean up code (eg. a finally block), but then consider what happens when the out-of-band exception occurs in that clean up code? This leads to clean up code for the clean up code. But then that code is it self vulnerable so you need clean up code for the clean up code of the clean up code… it never ends!

There are solutions, but they are not easy to design (and tends to impact your whole design), and even harder to test—how to re-create all the cases (think combinatorial exposition). Two possible routes are:

Work on copies of state, update the copies and then atomically swap current for new state. If there is an out-of-band exception then the original state remains (and finalisers can clean up the temporary state).

This is rather like the function of database transactions (albeit RDBMSs work with locks and transaction log files).

It is also similar to the approaches to achieving the "strong exception guarantee" developed in the C++ community in response to a paper questioning if exceptions could ever be safe (C++ of course has no GC/finaliser queue to clean up discarded objects). See Herb Sutters "Guru of the Week #8: CHALLENGE EDITION: Exception Safety" for the solution.

In practice this is hard to achieve unless your state can be encapsulated in a single reference.

Look at "Constrained Execution Regions", but not the limitations on what you can do in these cases. (MSDN Magazine had an introductory article (introduction to the subject, not introductory level), from .NET 2 beta period2).

In practice if you have to do this, using approach #2 to manage the state change under #1 is probably the best approach, but getting it right, and then validating that it is correct (and the correctness is maintained) is hard.

Summary: It's a bit like optimisation: rule 1: don't do it; rule 2 (experts only): don't do it unless you have no other option.

1 A ThreadAbortException is not the only such exception.

2 So details have possibly changed.