C # ішіндегі функция қайталанбайды, ол енді артық болмайды

Менде SOAP интерфейсі деп аталатын сынып бар және деректердің жиынын алады. Дегенмен, егер бұл сұраныс орындалмаса, ол ерекше жағдайды шығарады. Бұл жақсы. Дегенмен, менің бағдарлама осы қоңырауды қайтадан жасауға тырысқым келеді. Егер бұл уақытты жоғалтса, мен бұл қоңыраудың сәтті орындалуын жалғастырғым келеді. Мұны қалай орындауға болады?

Мысалға:

try
{
   salesOrdersArray = MagServ.salesOrderList(sessID, filter);
}
catch
{
   ?? What Goes Here to FORCE the above line of code to rerun until it succeeds.
}
7
Ерекшені тастамайынша, күту уақытын көбейтіңіз?
қосылды автор ChaosPandion, көзі
Осы жауаптардың барлығының біреуі сізден нақты ерекше жағдайды ұстап алуды талап етпейді. Егер сынақ блокта salesOrderList алу үшін жарамсыз күйдегі нысандар бар болса не болады? Қайталап көру ешқашан табысқа жетпейді.
қосылды автор Marc, көзі
Сіз әдісті тек қана аулау блогынан, BUT - қоңырауды ұзақ уақыт бойы өшірсе не болады? 24 сағат ішінде рекурсивті түрде жұмыс істеу әдісі қажет пе? Мен бірнеше рет қайталауға шектеу ұсынамын.
қосылды автор Tim, көзі

11 жауаптар

Сізге мәңгілікке айналдыру қажет:

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 (дәстүрлі емес әдіс атауы, btw) ArgumentNullException all себебі сізде қате бар және filter нөлге тең ... сіз шынымен шынымен 100% процессорды біржола байланыстырғыңыз келеді?

16
қосылды
@Tim: Мен төмендегі параграфты қосып отырдым - негізінен кодекс тікелей сұраққа жауап береді, бірақ тармақ бұл жақсы идея емес екенін түсіндіреді :)
қосылды автор Jon Skeet, көзі
@psyklopz: Сіз catch блогында ерекше жағдай түрін көрсетесіз: catch (SoapException) және т.б. Сіз бірнеше ұстап блоктарда бірнеше ерекшелік түрлерін көрсете аласыз.
қосылды автор Jon Skeet, көзі
Мен мұндай нәрсені жасаған кезде, кейбір қызмет онлайн режимінде оралуын күткен процессордың 100% -ын пайдаланбау үшін тиісті уақыт ұзақтығы Ұйқы -қа қоямын. Мен тіпті кішігірім желілік глиттерден жылдам қалпына келтірілу үшін шектеулі экспоненталық кері схеманы (TCP сияқты) қамтуы мүмкін, бірақ егер қызмет ұзақ уақыт бойы өшірілсе, бірнеше минут сайын әрекет жасайды.
қосылды автор Gabe, көзі
Арнайы ерекше жағдайларды қоспағанда, сіз өзіңіздің редакцияңыздағы сұраққа жауап бере бастадым.
қосылды автор Marc, көзі
Бұл (әлеуетті) жүйе ресурстарын байланыстыру және/немесе қоңырау қолданбасының жауап бермеуі мүмкін емес пе? Мен үшін ең жақсы шешім ретінде көрінбейді ...
қосылды автор Tim, көзі
Сіз сондай-ақ ағымдағы уақытты ала аласыз, содан кейін diff b/w дейін күтуге болады, ал енді> 5 сек, одан кейін шығыңыз (немесе ұзақ уақыт қажет)
қосылды автор Mr Universe, көзі
Мен белгілі бір ерекшеліктерді, SOAP қателерін және т.б. білемін. Үзілістің қуанышын, рахметін ұмытып кет.
қосылды автор psyklopz, көзі

Егер сіз күту уақытын өзгерте алмасаңыз, төменде жұмыс істеу керек. salesOrdersArray параметрін null күйіне келтіру керек.

while(salesOrdersArray == null)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
      //Log failure
    }
}
4
қосылды
+1: Маған бұл Жонның жауапынан сәл артық ұнайды. Менің ойымша, бұл циклдің соңғы күйін анық көрсетеді.
қосылды автор Brian, көзі

Бұл басқарудың ағыны ретінде ерекше жағдайларды пайдалануға жақсы идея емес, бірақ бұл сіз сұрағандарды орындайды.

bool Caught = true;
while (Caught)
try
{
    salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    Caught = false;
}
catch
{
    Caught = true;
}
1
қосылды

Қызметтік қоңырауды сақтау үшін транзакциялық кезек (MSMQ) қолданамын. Егер цикл сәтсіз болса, хабар тоқтап, транзакциякопта қызметке қоңырау шалады. Хабарламада аяқталатын уақытты қосу арқылы кідіріс уақытын белгілеуге болады. Егер сіз шынымен сенімді шешімді алғыңыз келсе, бұл шешім жақсы, себебі мен бұл операцияның маңызды екенін айтқым келеді.

1
қосылды

Сіз тырнақ конструкциясында try/catch блогын орналастыруыңыз керек. Процессордың 100% -ын пайдаланбау үшін, Thread.Sleep-ті catch блогында орналастырғыңыз келмесе, әрбір кезде ерекше жағдай орын алады, процессорды басқа нәрселермен айналысуға босатады.

// 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 ауыстыруға керекке нақты атаумен ... Мен білмеймін, бұл нақты аты.

Сондай-ақ, миллисецтерде берілген ұйқы уақытын және қайталанатын соманы реттеп берсем, 1000 мы 100 рет қайталау 1 минуттан 40 секундқа барынша күтуге мүмкіндік береді, сонымен қатар операция уақыты өзі.

1
қосылды

Тырысу

bool failed = false;
do {
 Тырысу
 {
  salesOrdersArray = MagServ.salesOrderList(sessID, filter);
 }
 catch
 {
  failed = true;
 }
} while(failed);

Бұдан кейінгі мінез-құлықсыз шексіз циклды тудыруы мүмкін, бірақ бұл нәтиже ешқашан болмайды.

0
қосылды

Мен мұны шексіз сандар үшін жасауға кеңес бермейтін болсам да, сол бір сөйлемнен бөлек функцияны жасай аласыз:

void GoConnect()
{
    try
    {
        salesOrdersArray = MagServ.salesOrderList(sessID, filter);
    }
    catch
    {
        GoConnect();
    }
}
0
қосылды
bool repeat = true;
while (repeat)
{
    try
    {
       salesOrdersArray = MagServ.salesOrderList(sessID, filter);
       repeat = false;
    }
    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;
        }
    }

Мәңгілікке әрекет ету, шексіз процесс болуы мүмкін, себебі жақсы идея емес. Егер сіз өз мақсатыңызға жету үшін көптеген әрекеттер қажет деп ойласаңыз, мұнда үлкен санды орнатыңыз.

Thread.Sleep (1000) Send (data); әрекетінен кейін бірнеше миллисекундтарды күтіп, , бұл сценарий үшін дана екенін ойласаңыз, күту уақытын көтеру немесе азайту үшін attempNumber айнымалысын пайдаланыңыз.

0
қосылды
неге мен? Менің түсінігім Джон Скитпен де жазылған кодтың астында
қосылды автор Renato Gama, көзі
thanks @asawyer бұл туралы білмеді, сондықтан менің жауапымды редакцияладым! қазір бұл жақсы?
қосылды автор Renato Gama, көзі
бұл шын мәнінде мағынасы ...! ешқашан бұлай ойлаған емеспін ... скудость үшін кешіріңіздер, қазір не туралы?
қосылды автор Renato Gama, көзі
throw ex; Бұны жасамаңыз!
қосылды автор asawyer, көзі
Екі нәрсе: 1- Сіз базалық ерекшелік сыныбын ұстағыңыз келмейді, және егер жасасаңыз, журналға жазу үшін тек қана маңызды, содан кейін throw again. 2 - Негізгі Exception сыныбын ешқашан тастамаңыз. Сіз тұтынушы кодын Exception аулаудың жаман тәжірибесіне мәжбүр етесіз. Неғұрлым сәйкес келетін қосалқы классты пайдаланыңыз немесе өзіңізді жасаңыз.
қосылды автор asawyer, көзі
Ең жақсы тәжірибелерді оқып үйрену үшін аз уақыт бөліңіз және сіз ешқашан бизнеске қатыссыз. Херес жұп жақсы сілтемелер: blogs.msdn. com/b/ericlippert/archive/2008/09/10/hellip; codeproject.com/KB/architecture/exceptionbestpractices.aspx
қосылды автор asawyer, көзі
Сіз редакцияны білдіресіз бе? Жақсы көрінеді! :)
қосылды автор asawyer, көзі

Мынадай нәрсені көріңіз:

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

Өңдеу: Wow! Ұлы ақыл-ойлар да ойлайды! :)

0
қосылды
while(salesOrdersArray == null){

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

Бұл мәңгілікке орындалады және баяу ілмек ретінде ерекше жағдайларды пайдаланады. Өзіңіздің функцияңызды алып тастаудың орнына нөлді қайтаратын тәсіл бар ма? Егер сіз бұл қоңырау үнемі үзілмейді деп күтсеңіз, try/catch блогын пайдаланбаңыз.

0
қосылды