[英]Repeating a function in C# until it no longer throws an exception
我有一個調用SOAP接口的類,並獲取一個數據數組。 但是,如果此請求超時,則會引發異常。 這很好。 但是,我希望我的程序再次嘗試進行此調用。 如果它超時,我希望繼續撥打這個電話,直到它成功為止。 我怎么能做到這一點?
例如:
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
?? What Goes Here to FORCE the above line of code to rerun until it succeeds.
}
你只需要永遠循環:
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
是null ...你真的想永遠占用100%的CPU嗎?
如果您無法更改超時,則以下情況應該有效。 salesOrdersArray應初始化為null
。
while(salesOrdersArray == null)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
// Log failure
}
}
使用異常作為控制流程並不是一個好的理想選擇,但這可以滿足您的要求。
bool Caught = true;
while (Caught)
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
Caught = false;
}
catch
{
Caught = true;
}
您必須將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次重復1000ms產生最長等待1分40秒,加上操作時間本身。
我將使用事務性隊列(MSMQ)來存儲服務調用。 循環將使消息出列並在TransactionScope中調用服務,如果調用失敗,則消息似乎仍在隊列中。 可以通過在消息中添加到期時間來指定總體超時。 如果你真的想要一個可靠的解決方案,這個解決方案是好的,因為我猜這個操作是至關重要的。
bool repeat = true;
while (repeat)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
repeat = false;
}
catch
{
}
}
嘗試
bool failed = false;
do {
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
failed = true;
}
} while(failed);
你所追求的行為可能會導致無限循環,如果這永遠不會成功...
嘗試這樣的事情:
var failed = true;
while (failed)
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
failed = false;
}
catch
{
}
}
編輯:哇! 英雄所見略同! :)
雖然我不建議你無數次執行此操作,但你可以用一個句子創建一個單獨的函數:
void GoConnect()
{
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
GoConnect();
}
}
while(salesOrdersArray == null){
try
{
salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch(salesOrderException e)
{
log(e.message);
}
}
這將永遠運行,並使用異常作為一個緩慢的循環。 有沒有辦法可以修改你的函數,它返回null,而不是拋出異常? 如果您希望此調用會定期失敗,請不要使用try / catch塊。
我按照這種模式來解決這個問題:
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 發送之前(數據); ---例如,如果你認為它適用於你的場景,你可以使用attemptNumber變量來增加或減少這個等待時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.