2008-09-18 47 views
0

我有一個Windows Workflow應用程序,它使用我爲COM自動化編寫的類。我使用COM從我的課程中打開Word和Excel。通過COM互操作處理對象生命週期的最有效方法是什麼?

我目前在我的COM幫助程序中實現IDisposable並使用Marshal.ReleaseComObject()。但是,如果我的工作流失敗,Dispose()方法未被調用,Word或Excel句柄保持打開狀態,並且我的應用程序掛起。

這個問題的解決方案非常簡單,但並非只是解決它,我想了解一些東西,並深入瞭解使用COM的正確方法。我正在尋找處理擁有COM句柄的類的生命週期的「最好」或最有效和最安全的方法。模式,最佳實踐或示例代碼將會有所幫助。

回答

1

我看不到你沒有調用Dispose()方法的失敗。我使用順序工作流進行了測試,該工作流僅包含只引發異常的代碼活動,並且我的工作流的Dispose()方法被調用兩次(這是因爲標準的WorkflowTerminated事件處理程序)。請檢查下面的代碼:

的Program.cs

class Program 
    { 
     static void Main(string[] args) 
     { 
      using(WorkflowRuntime workflowRuntime = new WorkflowRuntime()) 
      { 
       AutoResetEvent waitHandle = new AutoResetEvent(false); 
       workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) 
       { 
        waitHandle.Set(); 
       }; 
       workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) 
       { 
        Console.WriteLine(e.Exception.Message); 
        waitHandle.Set(); 
       }; 

       WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1)); 
       instance.Start(); 

       waitHandle.WaitOne(); 
      } 
      Console.ReadKey(); 
     } 
    } 

Workflow1.cs

public sealed partial class Workflow1: SequentialWorkflowActivity 
    { 
     public Workflow1() 
     { 
      InitializeComponent(); 
      this.codeActivity1.ExecuteCode += new System.EventHandler(this.codeActivity1_ExecuteCode); 
     } 

     [DebuggerStepThrough()] 
     private void codeActivity1_ExecuteCode(object sender, EventArgs e) 
     { 
      Console.WriteLine("Throw ApplicationException."); 
      throw new ApplicationException(); 
     } 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing) 
      { 
       // Here you must free your resources 
       // by calling your COM helper Dispose() method 
       Console.WriteLine("Object disposed."); 
      } 
     } 
    } 

我缺少的東西?關於活動(以及工作流程)對象的生命週期相關方法,請查看此帖:Activity "Lifetime" Methods。如果您只想要一個關於處理的通用文章,請檢查this

+0

再一次,你發現。問題不在於我的COm處理(我多年來一直在這樣做),而在於我處理工作流運行時的方式。非常感謝! – 2008-09-19 14:33:03

0

基本上,在工作結束時,不應該依賴手動代碼來調用Dispose()。你可能有像現在這樣的權利:

MyComHelper helper = new MyComHelper(); 
helper.DoStuffWithExcel(); 
helper.Dispose(); 
... 

相反,你需要使用try塊來捕獲可能會觸發的任何異常並致電處置在這一點上。這是典型的方法:

MyComHelper helper = new MyComHelper(); 
try 
{ 
    helper.DoStuffWithExcel(); 
} 
finally() 
{ 
    helper.Dispose(); 
} 

這是所以常見的是C#具有生成特殊構建體完全相同的代碼[見注]如上所示;這是你應該做的大部分時間(除非你有一些特殊對象的構造語義進行手動模式像上面更容易使用):

using(MyComHelper helper = new MyComHelper()) 
{ 
    helper.DoStuffWithExcel(); 
} 

編輯
注意:生成的實際代碼比上面的第二個示例稍微複雜一些,因爲它還引入了一個新的本地作用域,使得幫助對象在using塊之後不可用。就好像第二個代碼塊被{}包圍。爲了澄清解釋,省略了這一點。

相關問題