2011-02-28 39 views
3

我有一個管理進程的類。當在這個類上調用Stop()Dispose()時,它會首先向進程發送TCP命令,要求它關閉自己,然後在1秒鐘內檢查,如果不是關閉,請調用CloseMainWindow(),然後等待另一秒鐘,如果它仍在運行,致電Kill()自處理類

現在我有一個List<>這個類來管理一堆進程。當我想從列表中刪除它們時,我會手動呼叫Dispose(),然後Remove()。我想確保在我放棄唯一參考資料之前,我打電話給Dispose()。由於致電Dispose()需要至少2秒才能返回,因此如果我有5個物品需要移除,則需要一段時間。

因此,我打算有另一個函數SafeDispose(),然後Invoke()Dispose()然後返回。現在從列表中刪除這些並且調用SafeDispose()而不是Dispose()將立即進行,而類本身緩慢地處置它們。

建議這樣做嗎?

回答

0

使用的事件,而不是

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MyClass c = new MyClass()) 
     { 
      c.Disposed += MyClass_Disposed; 
      Console.WriteLine("Press any key to dispose"); 
      Console.ReadKey(); 
     } 
     Console.WriteLine("Press any key to finish"); 
     Console.ReadKey(); 
    } 

    static void MyClass_Disposed(object source, EventArgs e) 
    { 
     Console.WriteLine("I've been disposed"); 
    } 
} 


class MyClass : IDisposable 
{ 
    public event EventHandler Disposed; 

    public void Dispose() 
    { 
     if (this.Disposed != null) 
      this.Disposed(this, EventArgs.Empty); 
    } 
} 
+0

我不明白爲什麼你需要在一個強加的事件當沒有必要的時候上課。你基本上把一個回調硬連接到Dispose方法上。 – 2011-02-28 03:34:23

+0

@Sleeper。我想你在我編輯它之前閱讀我的答案。這個事件不是強加的。 – Eduardo 2011-02-28 03:38:10

+0

我沒有看到這個解決方案的重點。射擊事件也是一種阻擋方法,所以它仍然需要等待。 – faulty 2011-02-28 04:46:14

0

使用異步方法調用處置的對象,然後從列表中刪除。

假設您有一個要處置的類foo的列表,名爲foos

var iars = new List<IAsyncResult>(); 
Action<IDisposable> disposeAction = a => a.Dispose(); 
foreach(var foo in foos) 
    iars.Add(disposeAction.BeginInvoke(null, null)); 
foreach(var iar in iars) 
    disposeAction.EndInvoke(iar); 
foreach(var foo in foos) foos.Remove(foo); 

如果你在.NET 4.0中,你可以做到這一點與更多的效益分析並行庫。 編輯 - List.Remove線程安全的常見需求。 至於異常安全。 Dispose()方法不應該首先拋出異常。

+0

該類不應該關心從列表中刪除自己。它既不知道該名單的存在。抽象。 – Eduardo 2011-02-28 03:33:52

+0

呃,實際上它沒有。異步方法在** foo對象的外部完成。 – 2011-02-28 03:37:35

+0

儘管我同意一般方法,但代碼有兩個問題:1)線程安全問題('List .Remove')和2)異常安全性(從'BeginInvoke'拋出的異常會使進程崩潰)。更好的解決方案是從「Task」中調用Dispose,等待所有任務,然後從列表中刪除它們。 – 2011-02-28 03:48:32

2

基本上,你是在暗示,保留Dispose「原樣」,而是有一個幫助器方法,將對象異步地撕下來 - 這是附着在對象上的。

這是明智的嗎?

也許,關於引入線程的棘手問題是所有線程的混亂。

  • 當另一個方法訪問異步處理對象時會發生什麼?
  • 當另一個AsyncDispose被同時調用時會發生什麼?
  • 錯誤是如何傳播的?
  • 這會引入僵局嗎?
  • 在不同的線程(和不同的對象)上運行大量的處置會導致任何問題嗎? (如用完tcp插座)

如果你能以滿意的方式回答所有問題,那麼也許吧。

請記住,您也可以分拆一個線程中處理所有到期和在一個單獨的線程這樣做(作爲另一種選擇)的UI

+0

這個班級是內部的,只能由我自己使用。一旦從列表中刪除,就沒有更多的參考,所以再次調用AsyncDispose是沒有機會的,避免了併發問題和死鎖。每個流程管理類都持續了至少10秒到幾個小時,關閉它們只需要幾分之一秒,而我一次不會超過10個,所以線程數應該在安全級別。當需要殺死時,在這種情況下,錯誤並不重要,如果tcp連接關閉,進程將自動關閉。順便說一句,這是一個非UI類 – faulty 2011-02-28 04:56:12