由於您沒有catch塊,因此不能保證最終會被執行。從MSDN - try-finally (C# Reference)和"Locks and exceptions do not mix" (Eric Lippert)
在一個處理的異常,與之關聯的finally塊保證 中運行。但是,如果異常未處理,則,finally塊的執行取決於異常展開操作如何觸發 觸發。這反過來又取決於你的電腦設置方式。
然後從提到的鏈接(Unhandled Exception Processing In The CLR)那裏有各種各樣的考慮可能意味着你最終以一個終止的線程。我不老實地知道這是否會讓你鎖定鎖對象。
如果你想確保:
- 您解除鎖定;但
- 你不想在這個級別來處理異常,而不是你希望由更高級別的異常處理程序處理
然後做:
TheXmlType xml = null;
Monitor.Enter(Lock);
bool inLock = true;
try {
...
xml = filter.Xml; // put this here in case it throws an exception
inLock = false; // set this here in case monitor.exit is to
// throw an exception so we don't do the same all over again in the catch block
Monitor.Exit(Lock);
return xml; // this is fine here, but i would normally put it outside my try
}
catch (Exception) {
if (inLock) Monitor.Exit(Lock);
throw;
}
但是,請注意:不要不會使用catch (Exception)
來隱藏異常,只有當您重新拋出異常時纔可以。人們還建議你有一個return
聲明,通常這將在你的try塊之外。
編輯:
與測試程序確認,並從MSDN - Exceptions in Managed Threads
與.NET Framework 2.0版,公共語言運行庫 允許線程最未處理的異常進行 啓動自然。在大多數情況下,這意味着未處理的異常 會導致應用程序終止。
所以,如果你不處理你的異常,你的應用程序將崩潰(你不必擔心鎖定)。如果你確實處理了它,那麼你的原始代碼將會執行它,最終會被阻止,並且你沒事。
編輯2:測試代碼更新,因爲它沒有正確地說明了非火終於:
class Program
{
static void Main(string[] args) {
Program p =new Program();
p.Start();
Console.WriteLine("done, press enter to finish");
Console.ReadLine();
}
private readonly object SyncRoot = new object();
ManualResetEvent mre = new ManualResetEvent(false);
private void Start() {
/*
* The application will run the thread, which throws an exception
* While Windows kicks in to deal with it and terminate the app, we still get
* a couple of "Failed to lock" messages
* */
Thread t1 = new Thread(SetLockAndTerminate);
t1.Start();
mre.WaitOne();
for (int i = 0; i < 10; i++) {
if (!Monitor.TryEnter(this.SyncRoot, 1000)) {
Console.WriteLine("Failed to lock");
}
else {
Console.WriteLine("lock succeeded");
return;
}
}
Console.WriteLine("FINALLY NOT CALLED");
}
public int CauseAnOverflow(int i)
{
return CauseAnOverflow(i + 1);
}
public void SetLockAndTerminate() {
Monitor.Enter(this.SyncRoot);
Console.WriteLine("Entered");
try {
mre.Set();
CauseAnOverflow(1); // Cause a stack overflow, prevents finally firing
}
finally {
Console.WriteLine("Exiting");
Monitor.Exit(this.SyncRoot);
}
}
}
這只是編寫** lock **語句的難題。否則確保只有一個進程可以使用SqlLite,您將需要使用命名的Mutex。 – 2013-05-11 11:07:15