[英]How can I structure a try-catch-finally block to handle errors inside finally?
我在調用第三方C ++ dll時遇到問題,我使用DllImport
將其包裝在一個類中以訪問其功能。
dll要求在使用前打開一個會話,該會話將返回一個整數句柄,用於在執行操作時引用該會話。 完成后,必須使用相同的句柄關閉會話。 所以我做了這樣的事情:
public void DoWork(string input)
{
int apiHandle = DllWrapper.StartSession();
try
{
// do work using the apiHandle
}
catch(ApplicationException ex)
{
// log the error
}
finally
{
DllWrapper.CloseSession(apiHandle);
}
}
我的問題是,CloseSession()有時會導致有問題的Dll在運行線程時拋出錯誤:
System.AggregateException:發生一個或多個錯誤。 ---> System.AccessViolationException:嘗試讀取或寫入受保護的內存。 這通常表明其他內存已損壞。
我不確定要停止此錯誤有很多辦法,因為它似乎是由於以線程方式使用Dll引起的-它應該是線程安全的。 但是,由於我的CloseSession()函數除了調用Dll的close函數外什么也不做,因此我沒有太大的空間來“修復”任何東西。
但是,最終結果是會話無法正確關閉。 因此,當該過程再次嘗試執行時(應執行的操作),它將遇到一個打開的會話,並不斷拋出新的錯誤。 那屆絕對必須關閉。
我對如何設計一個更健壯的錯誤處理語句感到困惑,該語句將確保會話始終關閉?
我將更改包裝器,以包括處理外部資源並包裝手柄。 即,不是用句柄表示會話,而是用包裝對象表示會話。
此外,將對DLL的調用包裝在lock
語句中(如@Serge所建議的那樣),可以完全防止多線程問題。 請注意,鎖定對象是靜態的,因此所有DllWrappers都使用相同的鎖定對象。
public class DllWrapper : IDisposable
{
private static object _lockObject = new object();
private int _apiHandle;
private bool _isOpen;
public void StartSession()
{
lock (_lockObject) {
_apiHandle = ...; // TODO: open the session
}
_isOpen = true;
}
public void CloseSession()
{
const int MaxTries = 10;
for (int i = 0; _isOpen && i < MaxTries; i++) {
try {
lock (_lockObject) {
// TODO: close the session
}
_isOpen = false;
} catch {
}
}
}
public void Dispose()
{
CloseSession();
}
}
請注意,這些方法現在是實例方法。
現在,您可以使用using語句確保關閉會話:
using (var session = new DllWrapper()) {
try {
session.StartSession();
// TODO: work with the session
} catch(ApplicationException ex) {
// TODO: log the error
// This is for exceptions not related to closing the session. If such exceptions
// cannot occur, you can drop the try-catch completely.
}
} // Closes the session automatically by calling `Dispose()`.
您可以通過調用此類Session
和方法Open
和Close
來改善命名。 此類的用戶不需要知道它是包裝器。 這只是一個實現細節。 而且,這些方法的命名現在是對稱的,無需重復使用Session
名稱。
通過封裝所有與會話相關的內容,包括錯誤處理,從錯誤情況中恢復以及資源的處置,您可以大大減少代碼中的混亂情況。 Session
類現在是一個高級抽象。 舊的DllWrapper
介於低級和高級之間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.