2011-07-13 19 views
2

我的Web服務有這個代碼鎖定在C#的Web服務超時時間

lock(typeof MyWebServiceClass) 

那麼我所說的第三方不變的代碼,它永遠不會返回。繁榮! BAM!

我現在永久鎖定,我的網站崩潰。

這絕不會返回只發生一次在很長一段時間。

是否有可能創建超時的鎖定? IE將代碼鎖定5分鐘然後釋放鎖定?

+0

5分鐘是一個很長的時間在計算機世界的鎖... –

+1

聽起來像它卡在*致命的擁抱*(觸發恐怖音樂) –

+0

會有什麼用?調用代碼仍然處於鎖定部分。您可以使用超時獲取鎖,並從那裏進行編碼。 –

回答

2

,與其建立定時鎖,我會通過將其放入單獨的線程/任務來限制您的第三方請求。然後,啓動線程(或任務,如果.NET 4.0和TPL可用),並加入超時響應。如果加入超時,則取消線程(或在TPL任務上調用取消標記)。

0

是否有可能創建超時鎖?

是的,這種不愉快的情況通常被認爲是deadlock

通常它是很好的做法,鎖定,而不是鎖定在實例字段或類本身的靜態私有對象:

private static object _syncRoot = new object(); 

然後:

lock(_syncRoot) { 

} 
+0

看來他的問題更多是指他在鎖中執行的代碼需要非常非常長的時間,有時根本不會返回... –

+0

@James Michael Hare,是的,如果您使用實例字段進行鎖定,則會大大增加陷入死鎖的可能性。 –

+0

非常真實。我同意他不應該鎖定一個類型實例,也許如果我們知道更多關於他在哪裏/如何使用他的鎖,我們會知道更多,如果它是一個僵局或長期請求。無論哪種方式,他都應該按照你所說的將鎖定對象清理成一個私有實例。 –

0

如果第三方API有取消機制,請使用該機制。

lock(typeof MyWebServiceClass) 
{ 
    if (ThirdPartyApiThatAcceptsTimeout(TimeSpan.FromMinutes(5))) 
    { 
    // The call was successful so proceed. 
    } 
    else 
    { 
    // The call timed out so bail out. 
    return; 
    } 
} 

但是,我高度懷疑這個API沒有取消機制,所以你提出了這個問題。如果是這種情況,那麼這種情況就會成倍地增加。

樸素的方法是將API調用推遲到另一個線程。如果線程沒有及時響應,則可以放棄它。

lock(typeof MyWebServiceClass) 
{ 
    var thread = new Thread(
    () => 
    { 
     ThirdPartyApiThatCouldBlockIndefinitely(); 
    }); 
    thread.Start(); 
    if (thread.Join(TimeSpan.FromMinutes(5)) 
    { 
    // The call was successful so proceed. 
    } 
    else 
    { 
    // The call timed out so bail out. 
    thread.Abort(); 
    return; 
    } 
} 

雖然這有很多問題。首先,不保證該線程將接受中止請求。從2.0開始,CLR中有特殊的規則決定何時可以向線程注入異常。我相信CLR將在非託管代碼執行時推遲注入。所以如果你的API是不受管理的,那麼中止可能不起作用。此外,由於線程可能捕獲ThreadAbortException並忽略它,因此放棄是自願的。其次,放棄是危險的,因爲放棄可以異步注入。這使得防止腐敗共享狀態變得非常困難。這就是AppDomain在中止後通常被終止的原因。

處理此問題最安全的方法是將API調用放入單獨的進程中。您將不得不使用.NET Remoting,WCF,管道等進程間通信協議來傳輸數據到/從該調用中,這將是一個真正的難題。但是,這將是最安全的,因爲您可以安全地終止進程而不會破壞調用方的AppDomain。

我真的感覺到你,因爲這個問題很難正確解決。