2011-03-08 30 views
3

我正在使用信號量來限制應用程序可以運行的併發實例的數量。處理中的自動信號量釋放退出

過程可以有多種終止方式。是否可以創建Semaphore,以便在流程退出時自動釋放?

編輯:

我想一些神奇的自動清理信號燈「提出」狀態的過程中擁有它在退出或崩潰。只要確定它已被清除,無論如何。

更多:

我尋找它的任何可行的選擇,考慮到:

  • 這將是偉大的,沒有外部應用程序需要得到保持在受保護的應用
  • 的每個實例
  • 它不一定是信號量 - 任何具有COUNTER並且在所有者進程死亡後自動釋放的同步對象都會很好,即使它在作弊
  • 我正在使用.NET 2.0,無法移動到新版本離子在這個項目上,但可以使用C/C++和OP間利用的東西,如果有什麼

回答

4

您可以掛接到AppDomain.ProcessExit事件執行像釋放信號的任何清理操作。

通常,指定的信號量旨在跨進程協調資源,而不會考慮特定的進程生命週期。在.NET信號燈由native Windows semaphore objects支持和MSDN說:當其最後一個句柄已關閉

信號燈對象被銷燬。關閉句柄不會影響信號量;因此,確保在關閉句柄之前或過程終止之前調用ReleaseSemaphore。

因此正確的方法是在進程終止之前的顯式處理。


更新 - 其他問題需要考慮:

  1. 如果它不是可行的AppDomain.ProcessExit事件手動處理「緊急」的發佈,考慮創建一個IDisposable包裝,將收購的信號它的構造函數並在Dispose方法中釋放它。
  2. 另一個問題是:信號量是否是這種情況下的正確同步對象?難道一個簡單的(指定的)互斥體會更好地工作嗎?

更新 - 在應用程序崩潰的情況下或強制終止(即通過任務管理器)ProcessExit不會有被處理的機會。因此,多個進程之間共享的任何非託管資源可能無法正確完成/處理/處理。有關更多詳細信息,請參閱this article

一個可行的選項可能是creating a named pipe。命名管道的優點是一旦創建過程終止,它們就不再退出。根據MSDN:

請注意,命名管道的一個實例可能有多個關聯的句柄。當命名管道實例的最後一個句柄關閉時,總是會刪除一個命名管道的實例。

有兩個選項來限制管道實例的數量:

  1. 只是一個實例:通過在dwOpenMode參數指定FILE_FLAG_FIRST_PIPE_INSTANCE標誌,可以禁止管道的多個實例的創建。然後,嘗試創建管道的第二個進程將收到錯誤。
  2. 更多實例:通過指定nMaxInstances參數中允許的實例的數量。當允許N時,N+1 st進程將收到錯誤。
+0

你的回答是可以的,但我希望有一些魔法能夠在退出或崩潰時自動清理信號量的「提升」狀態。 – 2011-03-08 13:32:36

+0

編輯提供更多選項。 – 2011-03-08 13:41:45

+0

命名互斥體是否有數量?我使用它來限制運行的程序實例的數量(許可) – 2011-03-08 13:44:00

4

適當的答案是圍繞您的信號量實施「關鍵終結器」,以確保在所有情況下進行適當的清理。 ProcessExit不能保證在故障情況下執行,如強制AppDomain卸載由於非可捕獲的異常

更多信息@http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.criticalfinalizerobject.aspx, 引用(StackOverflowException和InvalidProgramException就是兩個很好的例子。):「通用語言運行時(CLR)保證所有關鍵的終止代碼都有機會執行,只要終結器遵循CER的規則,即使在CLR強制卸載應用程序域或中止線程的情況下。

1

如果不像Daniel,可以升級到.Net 3.5 a NamedPipeServerStream類可用來創建您的pipe

NamedPipeServerStream pipe; 
    try 
    { 
    pipe = new NamedPipeServerStream(name, PipeDirection.InOut, 3); 
    } 
    catch (IOException) 
    { 
    //Maximum number of instances reached (3). 
    } 

我建議您在退出過程之前在管道上保留一個靜態引用以避免終結。 管道的缺點是,你不能等到一個沒有輪詢的實例可用。

+0

從.NET 4.6起,有[NamedPipeServerStream.WaitForConnectionAsync](https:/ /msdn.microsoft.com/en-us/library/dn823300(v=vs.110).aspx)和[NamedPipeClientStream](https://msdn.microsoft.com/en-us/library/dn823299(v = vs 0.110)的.aspx)。 – 2016-06-13 21:55:37