2011-10-27 31 views
6

我有一個類調用SOAP接口,並獲取一個數組數組。但是,如果此請求超時,則會引發異常。這很好。但是,我希望我的程序再次嘗試進行此調用。如果超時,我希望它繼續進行此調用,直到成功。我怎樣才能做到這一點?在C#中重複一個函數,直到它不再拋出異常

例如:

try 
{ 
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
} 
catch 
{ 
    ?? What Goes Here to FORCE the above line of code to rerun until it succeeds. 
} 
+3

增加超時所以它不會拋出異常? – ChaosPandion

+0

您可以簡單地從catch塊中調用該方法,*但是* - 如果服務長時間停機會發生什麼情況?你想讓這個方法遞歸運行24小時嗎?我建議將它限制爲一組重試次數。 – Tim

+5

在所有這些答案中,沒有一個人告訴你要捕捉更具體的例外情況。如果你的try塊包含處於無效狀態的對象來獲得'salesOrderList'?重試永遠不會成功。 – Marc

回答

14

你只需要永遠循環下去:

while (true) 
{ 
    try 
    { 
     salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
     break; // Exit the loop. Could return from the method, depending 
       // on what it does... 
    } 
    catch 
    { 
     // Log, I suspect... 
    } 
} 

注意,你應該幾乎肯定實際上永遠循環下去。你應該幾乎肯定有最大數量的嘗試,並且可能只會捕獲特定的例外。捕獲所有例外永遠可能是慘不忍睹......想象一下,如果salesOrderList(非常規的方法名,順便說一句)拋出ArgumentNullException因爲你已經有了一個bug,filter爲空......你真的綁100你的CPU永遠佔你的%?

+1

難道這(可能)不會佔用系統資源和/或使調用應用程序無響應?聽起來不像是我最好的解決辦法... – Tim

+0

@Tim:我添加段落下方 - 基本代碼直接回答這個問題,但該段解釋說,這可能不是一個好主意:) –

+0

+1具體例外情況,我在編輯期間輸入了對該問題的評論。 – Marc

4

如果你不能改變超時,下面應該工作。 salesOrdersArray應該初始化爲null

while(salesOrdersArray == null) 
{ 
    try 
    { 
     salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    } 
    catch 
    { 
     // Log failure 
    } 
} 
+0

+1:我喜歡這個比Jon的回答好一點。我認爲這會讓循環的最終狀況更加明顯。 – Brian

1

它並不是一個很好的理念,可以將異常用作控制流,但是這樣做可以滿足您的要求。

bool Caught = true; 
while (Caught) 
try 
{ 
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    Caught = false; 
} 
catch 
{ 
    Caught = true; 
} 
0
bool repeat = true; 
while (repeat) 
{ 
    try 
    { 
     salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
     repeat = false; 
    } 
    catch 
    { 
    } 
} 
0

嘗試

bool failed = false; 
do { 
try 
{ 
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
} 
catch 
{ 
    failed = true; 
} 
} while(failed); 

你以後可能會導致無限循環,如果這永遠不會成功,但行爲...

0

嘗試是這樣的:

var failed = true; 
while (failed) 
{ 
    try 
    { 
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    failed = false; 
    } 
    catch 
    { 
    } 
} 

編輯:哇!英雄所見略同! :)

0

雖然我不建議你爲無數次做到這一點,你可以做一個單獨的函數的是一個句子:

void GoConnect() 
{ 
    try 
    { 
     salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    } 
    catch 
    { 
     GoConnect(); 
    } 
} 
0
while(salesOrdersArray == null){ 

    try 
    { 
    salesOrdersArray = MagServ.salesOrderList(sessID, filter); 
    } 
    catch(salesOrderException e) 
    { 
    log(e.message); 
    } 
} 

,這將永遠運行,使用異常作爲一個很慢的循環。有沒有辦法可以修改你的函數返回null,而不是拋出異常?如果您希望這個調用會定期失敗,請不要使用try/catch塊。

0

我遵循這個模式,以解決這個問題:

public void Send(String data, Int32 attemptNumber) 
    { 
     try 
     { 
      yourCodeHere(data); 
     } 
     catch (WebException ex) 
     { 
      if (attemptNumber > 0) 
       Send(data, --attemptNumber); 
      else 
       throw new AttemptNumberExceededException("Attempt number exceeded!", ex); 
     } 
     catch (Exception ex) 
     { 
      //Log pourpose code goes here! 
      throw; 
     } 
    } 

試圖永遠似乎不是因爲你最終可能會具有無限的過程是一個好主意。如果你認爲你需要很多嘗試來實現你的目標,那麼在這裏設置一個大數字。

我個人認爲它明智的等待幾毫秒或秒EAC嘗試後了Thread.Sleep(1000); callig前發送(數據); ---例如,您可以使用attempNumber變量來增加或減少等待時間,如果您認爲它適合您的方案。

+0

'罰球前;'不要那樣做! – asawyer

+0

爲什麼我不應該?我的觀點是一樣的喬恩斯基特,他寫道: – renatoargh

+2

不要扔'恩下面的代碼;'http://stackoverflow.com/questions/178456/what-is-the-proper-way-to-re-throw -an-exception-in-c http:// stackoverflow。com/questions/22623/net-throwing-exceptions-best-practices – asawyer

1

您必須將循環構造內的try/catch塊。如果你不想佔用你的處理器的100%在catch塊中放置一個Thread.Sleep,所以每當發生異常時,它都會等待一段時間,釋放處理器去做其他事情。

// iterate 100 times... not forever! 
for (int i = 0; i < 100; i++) 
{ 
    try { 
     // do your work here; 

     break; // break the loop if everything is fine 
    } catch { 
     Thread.Sleep(1000); 
    } 
} 

您還可以指定異常類型,以便只處理超時異常,以及其他類型的異常傳遞。

// iterate 100 times... not forever! 
for (int i = 0; i < 100; i++) 
{ 
    try { 
     // do your work here; 

     break; // break the loop if everything is fine 
    } catch (TimeOutException) { 
     Thread.Sleep(1000); 
    } 
} 

請注意,TimeOutException應該被替換爲異常的真實名稱......我不知道這是否是真實的名稱。

此外,在我提交的情況下,還要調整睡眠時間(毫秒數和重複次數),重複100次1000毫秒,最多等待1分40秒,再加上操作時間本身。

1

我將使用交易隊列(MSMQ)來存儲服務調用。循環將使消息出隊並在TransactionScope中調用服務,如果調用失敗,消息看起來仍然在隊列中。可以通過在消息中添加到期的時間來指定永久超時。如果你真的想要一個可靠的解決方案,這個解決方案是很好的,因爲我猜想調用這個操作是至關重要的。