3 Stimmen

Behandle abgebrochene Aufgabe und Aufgaben Ausnahmen in Task.WaitAll?

Ich verwende TPL, um eine Reihe von URLs abzurufen und dann einige Verarbeitungsschritte durchzuführen.

for (int i = 0; i < list.Count; i++)
{
    var tuple = list[i];
    string url = tuple.Item2;

    tasks[i] = httpClient.GetStringAsync(url).
        ContinueWith(task => {
        {
            ......

        });
}
Task.WaitAll(tasks);

Das Problem besteht darin, dass es beim Task.WaitAll Statement oft Ausnahmen zu geben scheint, weil ein Task abgebrochen wurde. Ich verstehe, dass httpClient.GetStringAsync nicht immer den Erfolg garantiert, daher möchte ich eine erneute Versuchslogik hinzufügen, wenn Ausnahmen auftreten. Wie sollte ich dabei am besten vorgehen?

2voto

i3arnon Punkte 106489

Sie können ganz einfach einen erneuten Versuch um GetStringAsync mit einer for-Schleife wickeln, die es versucht, bis es keine Ausnahme mehr gibt oder das Versuchslimit erreicht ist. Ich speichere die Aufgabe und extrahiere das Ergebnis daraus mithilfe von await, sodass, wenn das Wiederholungslimit ohne Erfolg erreicht wurde, die Ausnahme erneut ausgelöst wird:

async Task GetStringAsync(HttpClient client,string url, int retries)
{
    Task task = null;
    for (int i = 0; i < retries; i++)
    {
        try
        {
            task = client.GetStringAsync(url);
            await task;
            break;
        }
        catch
        {
            // Protokollieren
        }
    }

    return await task;
}

Sie könnten das sogar als Erweiterungsmethode auf HttpClient haben:

static async Task GetStringAsync(this HttpClient client, string url, int retries);

1voto

YK1 Punkte 7247

Wenn Sie async/await nicht verwenden möchten, können Sie die folgende Erweiterungsmethode als Ausgangspunkt verwenden.

static class HttpClientExtentions
{
    public static Task GetStringWithRetryAsync(this HttpClient client, string url, int retries)
    {
        var completion = new TaskCompletionSource();
        var ex = new List();

        Task getString = client.GetStringAsync(url);
        Action> continueAction = null;
        continueAction = (t) =>
        {
            if (t.IsFaulted)
            {
                ex.Add(t.Exception);

                if (retries-- > 0)
                {
                    getString = client.GetStringAsync(url);
                    getString.ContinueWith(continueAction);
                }
                else
                {
                    completion.SetException(new AggregateException(ex));
                }
            }
            else // Annahme des Erfolgs, Sie könnten auch Abbruch behandeln
            {
                completion.SetResult(t.Result);
            }

        };

        getString.ContinueWith(continueAction);

        return completion.Task;
    }
}

Verwenden Sie es folgendermaßen:

for (int i = 0; i < list.Count; i++)
{
    var tuple = list[i];
    string url = tuple.Item2;

    int retryCount = 3;
    var httpClient = new HttpClient(); // sollte für jede Anforderung ein neues Objekt erstellen
    tasks[i] = httpClient.GetStringWithRetryAsync(url, retryCount).
        ContinueWith(task => {
        {
            //......

        });
}
Task.WaitAll(tasks);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X