WF學習系列之六:工作流和宿主程序通訊異常引發的思考
1問題描述
工作流和宿主程序通訊的時候,經常碰到一下異常:
{"無法為實例 ID“c083a3ea-96e5-4bd2-bb9c-da2049244e08”傳遞接口類型“Mjgforever.Workflow.LocalServices.IOrderManagement”上的事件“OrderShipped”。"}
出現這種情況的時候,我們經常查閱msdn或去網上搜索,出現各種各樣的答案,然后去試各種解決方案,這種方式很浪費時間。為什么呢?這是因為沒有找到本質原因。
2 問題剖析
在書寫程序的時候,我們經常這樣捕獲異常:
try
{
if (eh != null)
{
OrderEventArgs e = new OrderEventArgs(workflowId, orderInfo);
e.WaitForIdle = true; //設置是立即引發事件還是工作流在引發前處于空閑狀態
eh(this, e);
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(">>> RaiseEvent Error: " + ex.Message + " <<<");
eventResult = false;
}
這樣寫有什么問題嗎?一個致命的問題是可能不能捕獲真正的異常!在這一點上,還是喜歡eclipse開發環境,它會提示我們要處理哪些異常,不知道微軟什么時候推出這種功能。另外,大家有什么好辦法可以可能的異常,最好帶提示性質的,畢竟每個類或函數引發的異常都去查的話,很費時,最后的解決方案就用Exception全代替了。在這點上,希望哪位高手指點一下。
這里就要講講Exception的InnerException 屬性。該屬性表示獲取導致當前異常的 Exception 實例。通過這個進行追蹤,我們可以找到真正的引發異常的原因。
3 InnerException介紹
屬性值
類型:System..::.Exception
一個 Exception 實例,它描述導致當前異常的錯誤。InnerException 屬性返回與傳遞給構造函數的值相同的值,或者,如果沒有向構造函數提供內部異常值,則返回 null 引用(Visual Basic 中為 Nothing)。此屬性為只讀。
備注
當異常 X 作為以前的異常 Y 的直接結果發生時,X 的 InnerException 屬性應當包含對 Y 的引用。
使用 InnerException 屬性獲得導致當前異常的異常集。
您可以創建對以前的異常進行捕捉的新異常。處理第二個異常的代碼可利用前一個異常的其他信息更適當地處理錯誤。
假定有一個可以讀取文件并格式化該文件中數據的函數。在此示例中,當代碼試圖讀取文件時引發 IOException。該函數捕捉 IOException 并引發 FileNotFoundException。IOException 可以保存在 FileNotFoundException 的 InnerException 屬性中,從而使捕捉 FileNotFoundException 的代碼可以檢查導致初始錯誤的原因。
保存對內部異常引用的 InnerException 屬性在初始化異常對象時設置。
下面的例子,大家可以試驗一下。
using System;
public class MyAppException : ApplicationException
{
public MyAppException(String message)
: base(message)
{ }
public MyAppException(String message, Exception inner) : base(message, inner) { }
}
public class ExceptExample
{
public void ThrowInner()
{
throw new MyAppException("ExceptExample inner exception");
}
public void CatchInner()
{
try
{
this.ThrowInner();
}
catch (Exception e)
{
throw new MyAppException("Error caused by trying ThrowInner.", e);
}
}
}
public class Test
{
public static void Main()
{
ExceptExample testInstance = new ExceptExample();
try
{
testInstance.CatchInner();
}
catch (Exception e)
{
Console.WriteLine("In Main catch block. Caught: {0}", e.Message);
Console.WriteLine("Inner Exception is {0}", e.InnerException);
}
}
}
4 實例分析
實例一:
{"無法為實例 ID“c083a3ea-96e5-4bd2-bb9c-da2049244e08”傳遞接口類型“Mjgforever.Workflow.LocalServices.IOrderManagement”上的事件“OrderShipped”。"}
InnerException屬性異常信息:
未啟用隊列“Message Properties
Interface Type:Mjgforever.Workflow.LocalServices.IOrderManagement
Method Name:OrderShipped
CorrelationValues:
”。
解決方案:這時只需要將代碼中注釋部分去掉就可以解決問題了。(e.WaitForIdle=true)
實例二
{"無法為實例 ID“c083a3ea-96e5-4bd2-bb9c-da2049244e08”傳遞接口類型“Mjgforever.Workflow.LocalServices.IOrderManagement”上的事件“OrderShipped”。"}
InnerException屬性異常信息:
程序集“OrderLocalServices, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中的類型“Mjgforever.Workflow.LocalServices.OrderManagementService”未標記為可序列化。
解決方案:直接定位到異常處。
5 小結
寫這篇文章主要向大家說明兩點:
(1)通過try … catch(Exception ex) { ex.Message};不一定能真正找到異常。我們要查找InnerException,直到該屬性為null。通過InnerException屬性定位真正的異常。
(2)vs在異常捕獲上,沒有eclipse好用,不知道大家有沒有好的解決方案,這樣我們在捕獲異常的時候可以很快的定位。如下所示,我們在捕獲IO異常的時候,有時會這樣寫。Eclipse就會建議我們寫,vs好像沒有這樣的功能。
catch(FileNotFoundException fnfe)
{
}
catch(IOException ioe)
{
}
catch(Exception ex)
{
}
最后,希望這篇文章能幫助大家迅速地查找錯誤的原因,避免漫無目的的搜素、求助,自己就可以搞定。
參考文獻
Msdn
posted on 2008-12-20 13:44 mjgforever 閱讀(1928) 評論(2) 收藏 舉報
浙公網安備 33010602011771號