簡體   English   中英

Thread.Abort() 損壞是否已本地化?

[英]Is Thread.Abort() corruption localized?

我知道由於各種原因調用 Thread.Abort() 是錯誤的

  1. 可以鎖定或在其他臨界區
  2. 可能在 I/O 操作中途,資源不會被清理
  3. 代碼可以吞下 ThreadAbortException
  4. 可能正在執行狀態更改操作,並使程序處於無效狀態。

假設線程的 Run() 方法:

  1. 不使用並發原語。
  2. 不執行任何 I/O。
  3. 不吞下此類異常。
  4. 暴露給只讀 API,因此無法更改程序狀態。

題:

如果我要在這樣的線程上調用 Abort(),是否造成了本地化的損壞(關於損壞)? 如在,我可以依靠我的程序,沒有最近中止的線程,繼續正常運行,還是我的整個進程/AppDomain/?? 然后可能損壞?

如果我刪除假設 1 和 2,是否會 abort() 損壞本地化到它訪問的特定並發原語和 i/o 資源? 還是可以向外傳播?

為什么我要鞭打 Thread.Abort() 死馬

我正在編寫一個胖客戶端 c# winforms 應用程序。 一個特性是用戶可以用 c# 編寫代碼,它在我的域對象上實現接口,然后可以插入我的應用程序(代碼通過 codedom 編譯成程序集並使用反射加載);

所以這個想法是用戶可以然后寫

public class CustomComputation : IComputationThing
{
    public void Compute(object context)
    {
        while (true) ;
    }
}

然后我可以反思生成的程序集,提取並實例化CustomComputation的實例,然后調用Compute(...); 很簡單的東西。

問題是用戶然后可以編寫上面的內容——一個無限循環,或者他決定不想等待的其他一些指數時間計算。

我正在嘗試研究我的選項,以便在用戶編寫一些無限循環(或指數時間等)代碼並希望從中中止時提供盡力而為的恢復。 雖然我確實打算要求用戶遵守取消模式,但最終不能保證他們會這樣做。

除非您了解 .NET 運行時庫的每一個細節,否則我懷疑您實際上能否保證您的假設(尤其是 4 和 1)。 違反假設 4 真正需要的是某個地方的單個靜態變量......

如果您使用生成的代碼,則單獨的AppDomain更容易停止和卸載,並且與線程不同,這可以作為托管進程正常生命周期的一部分來完成。

Thread.Abort() 肯定會污染您的 AppDomain,但我相信它也會破壞整個進程的穩定性。 我找不到這么快的鏈接。

因此,您必須在單獨的(一次性)流程中運行它。

由於用戶代碼非常動態(我希望典型的開發人員在編寫代碼時會進行數十次測試),因此無論如何您都希望將其放在單獨的 AppDomain 中,以便您可以卸載它。 如果是這樣,那么損壞只會影響單獨的應用程序域,無論如何它很快就會被卸載。

現在,我實際上開始想知道如果用戶代碼會產生另一個線程/應用程序域會發生什么,但這是另一個問題。 也許它可以通過一些權限解決,我對這些不是很熟悉。

查看 .net Terrarium 項目。 這是一個點對點演示應用程序,旨在演示 .net 框架的點對點功能和黑客安全。 開發人員可以匿名編寫和上傳 AI 代碼,以控制在數千台機器上作為點對點生態系統運行的虛擬玻璃容器中的昆蟲。

他們使用反射來確保上傳的代碼是安全的:你不能做 IO,鎖被限制,以及靜態變量。 他們還限制了你被允許“思考”的時間。 對這個應用程序來說足夠好的東西應該對你來說足夠好。

http://terrarium2.codeplex.com/

正如 Vilx 所提到的 - 您可以考慮將“用戶”代碼放在另一個 AppDomain 中。

事實上,從 .Net 3.5 開始,.Net Framework 已經包含了System.AddIn命名空間,它提供了一種在單獨的應用程序域(除其他外)中隔離“加載項”代碼的簡化方法。 如果不需要太多的跨域通信,這將為您提供一個很好的隔離級別,最壞的情況是您拆除特定於用戶代碼的 AppDomain。

有關詳細信息,請參閱此MSDN文章和CLR-Addin 團隊的博客

此外,雖然它不能解決所有問題,但您可以從觸發 Thread.Interrupt 開始。 這將導致 ThreadInterruptException 以類似於 ThreadAbortException 的方式引發,除了它只會在代碼中的定義點發生; 當線程阻塞或休眠時,而不是絕對在任何地方。 在您上面提到的緊密循環示例中,它可能無濟於事,但如果循環具有 Thread.Sleep(0),則可能會有所幫助。

你可以隨時畢業你的選擇:

  • 在 IComputationThing 上放置一個 Stop() 方法並要求用戶實現它。
  • 如果加載項沒有及時響應 Stop(),請嘗試 Thread.Interrupt(並記錄緊密循環者可能希望將 Thread.Sleep(0) 放入其循環中以讓步給另一個線程)
  • 如果失敗,請嘗試 Thread.Abort,或拆除應用程序域(可能直接后者)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM