2016-10-12 5 views
1

Ich habe eine List<Task<searchDataResponse>>, die etwa 30 Einträge enthält. Beim Debuggen dieser Liste kann ich nicht bestimmen, welcher der 30 Einträge ein bestimmter Eintrag ist.Wie teilt man Parameterwerte für fehlgeschlagene Methodenaufrufe mit?

Wie kann ich den Methodenaufruf (einschließlich des Eingabeparameterwerts) einer bestimmten Aufgabe in einer Sammlung von Aufgaben ermitteln?

Beispielcode:

var tasks = new List<Task<searchDataResponse>>(); 

for (var i = 0; i < 30; i++) 
{ 
    // GET DATE OF N DAYS PAST (UP TO 30) 
    var searchDate = DateTime.Now.AddDays(i * -1); 

    // CALL WEB SERVICE WITH A SPECIFIC DATE 
    var dateSpecificTask = wsClient.searchDataAsync(searchDate); 

    // ADD TASK TO LIST OF TASKS 
    tasks.Add(dateSpecificTask); 
} 

try 
{ 
    Task.WaitAll(tasks.ToArray()); 
} 
catch (AggregateException ae) 
{ 
    // SET ALL EXCEPTIONS AS HANDLED 
    ae.Handle(x => { return true; }); 
} 

// GET LIST OF FAILED TASKS 
var failedTasks = tasks.Where(x => x.Status == TaskStatus.Faulted).ToList(); 

// IDENTIFY FAILED TASKS - TRY TO IDENTIFY WHICH DATE SUPPLIED TO WEB SERVICE FAILED. 
foreach (var failedTask in failedTasks) 
{ 
    var failedMethod = failedTask.MethodSignature; //<---- here is what i want to do. Property 'MethodSignature' does not exist - this is merely an example of what I am attempting to do. 
} 

UPDATE - Einige der Kommentare deuten darauf hin, Menschen Sodbrennen über die Verwendung des Ausdrucks Methode Unterschrift hat. Was ich mit der Methodensignatur meine, ist die Methodensignatur einschließlich der Eingabeparameterwerte. Als solche habe ich den Fragetitel geändert, um genauer zu reflektieren, wonach ich suche. Mein Beispiel hat es erfunden und einfach. Es spiegelt nicht mein wirkliches Problem wider. Aber meine Frage bleibt - beim Betrachten der Liste der fehlgeschlagenen Aufgaben, wie ich die tatsächliche Methode ermitteln, die als Teil der Aufgabe aufgerufen wird. Ich kann anscheinend keine Eigenschaften der Aufgabe finden, die beschreiben, welche Methode den Fehler verursacht hat.

+3

Ich verstehe Ihre Frage nicht. Der Ausdruck "Methodensignatur" hat im Kontext von C# eine sehr spezifische Bedeutung und in Ihrem Codebeispiel haben Sie nur eine "Methodensignatur", d. H. Ihren Aufruf an "wsClient.searchDataAsync()", den alle Ihre Aufgaben verwenden. Wenn Sie nur wissen möchten, welche Aufgaben fehlgeschlagen sind, können Sie die Liste einfach mit einem Index wiederholen und diesen Index verwenden, um die an die Aufgabe übergebenen Daten neu zu berechnen. oder noch besser, speichern Sie diese Daten in einer anderen Liste, damit Sie sie korrelieren können. Worum geht es _speziell_ mit denen du Schwierigkeiten hast? Was meinst du wirklich mit "Methodensignatur"? –

+0

@PeterDuniho - im Beispiel-Code rufe ich die Web-Methode 30 Mal, jeweils mit einem etwas anderen Datum. Einige dieser Anrufe schlagen fehl.Ich suche Hilfe bei der Bestimmung der Daten, die beim Aufruf der Web-Service-Methode problematisch waren. Wenn ich die Sammlung von Aufgaben sehe, kann ich sehen, welche Aufgaben fehlgeschlagen sind, aber ich kann nicht mit den Daten korrelieren. Sie schlagen vor, eine andere zu korrelierende Liste zu haben. Würde dies auf der Position in der Liste basieren? Wenn Aufgabe 3 fehlgeschlagen ist, ist das Datum in Punkt 3 in der Korrelationsliste das fehlgeschlagene Datum? – barrypicker

+0

_ "Würde dies auf der Position innerhalb der Liste basieren?" _ - ja, natürlich. Deshalb würden Sie die Liste mit einem Index wiederholen (wie ich oben erwähnte). Zu Ihrer Information: Sie tun sich selbst keinen Gefallen, indem Sie den beleidigenden und entzündlichen Ausdruck "mit Sodbrennen" verwenden, um eine berechtigte Sorge über Ihren Missbrauch der technischen Terminologie zu beschreiben. –

Antwort

2
var operations = Enumerable.Range(0, 30) 
.Select(i => { 
    // GET DATE OF N DAYS PAST (UP TO 30) 
    var searchDate = DateTime.Now.AddDays(i * -1); 

    // CALL WEB SERVICE WITH A SPECIFIC DATE 
    var dateSpecificTask = wsClient.searchDataAsync(searchDate); 

    return new { i, searchDate, dateSpecificTask }; 
}.ToList(); 

Task.WaitAll(operations.ConvertAll(x => x.dateSpecificTask)); 

var failed = operation.Where(x => x.dateSpecificTask.State == Faulted).ToList(); 

Und in der failed Liste haben Sie jetzt alle Daten und Indizes.

+0

Danke usr - wieder scheint es, dass alle Antworten anzeigen, gibt es keine Möglichkeit, ein Task-Objekt für seine ursprüngliche Methode einschließlich Parameter abzufragen. Ihr Code veranschaulicht eine Umgehung, bei der die relevanten Datenelemente mit dem Aufgabenobjekt gepackt werden, um eine Korrelation zwischen den beiden zu ermöglichen. Ich werde mit dieser Strategie weitermachen - danke für das Beispiel! – barrypicker

+0

Eine Aufgabe hat keine Parameter. Du gibst ihm ein Lambda. Die Parameter sind darin verpackt, unzugänglich. Das ist eine gute Sache. Sie sind eingekapselt. Also müssen wir den Zustand um die Aufgabe herum lenken. – usr

+0

Ich schätze Ihre Gedanken. Ich würde denken, dass eine schreibgeschützte Eigenschaft, die den Lambda/Delegierten ausstellt, hilfreich gewesen wäre. Vielleicht empfinden andere dies als Sicherheitslücke. Ich weiß nicht. Ihre Lösung wird perfekt funktionieren. – barrypicker

1

Wenn Sie das Datum an eine fehlgeschlagene Aufgabe übergeben möchten, können Sie das Datum und die Aufgabe in Ihrer Sammlung speichern (und nicht nur die Aufgabe, wie Sie es jetzt tun).

Warum verwenden Sie keine Zwischenklasse zum Beispiel mit zwei Mitgliedern (Datum, Aufgabe)?

1

In dem von Ihnen geschriebenen Code finde ich einige Diskrepanzen, die meiner Meinung nach aus der Tatsache stammen, dass die Verwendung von Async-Await nicht gut verstanden wird, lassen Sie mich einige wichtige Aspekte hervorheben, bevor Sie eine alternative Lösung vorschlagen:

Anruf zu wsClient.searchDataAsync(searchDate) ist nicht awaited, die den Zweck eines Async Anruf besiegt, da, dass es eine Blockierung Synchronous Anruf wird, wenn Sie später ein all Async Anrufe in Task List warten auf kumulieren, aber das ist immer noch blockieren und nicht den Anruf Thread

freigeben 0

-Code Änderung:

  1. await den wsClient.searchDataAsync Async Ruf, der sicherlich Teil der async Methode

    for (var i = 0; i < 30; i++) 
    { 
        // GET DATE OF N DAYS PAST (UP TO 30) 
        var searchDate = DateTime.Now.AddDays(i * -1); 
    
    // CALL WEB SERVICE WITH A SPECIFIC DATE 
        var dateSpecificTask = await wsClient.searchDataAsync(searchDate); 
    
    // ADD TASK TO LIST OF TASKS 
        tasks.Add(dateSpecificTask); 
    } 
    
  2. Await die Aufgabensammlung Task.WhenAll nicht WaitAll, da außer Konsolenanwendung sein muss, wo es kein Ui-Kontext, WaitAll hat einen Bereich von Deadlock

den Code wie folgt ändern:

return await Task.WhenAll(tasks) Rückgabewert Task<searchDataResponse[]> sein würde, da alle Anrufe gleichen Rückgabetyp haben searchDataResponse

  1. nun den Kern Ihrer Frage, wie man Holen Sie sich die fehlgeschlagenen Aufgaben, obwohl Sie, wie in der obigen Frage akzeptiert, einen Wrapper erstellen können, der Task und andere Werte enthält und diese somit abbildet, aber warum nicht alle relevanten Details im Rückgabetyp searchDataResponse hinzufügen, dessen Schema Sie haben t gepostet, ist der Fehlerstatus kann hinzugefügt und aktualisiert werden in der gleichen dann von der Task<searchDataResponse[]> zurückgegeben von der Async Methode und alle t Hut Sie brauchen, ist:

Abwickelwerkzeug das Ergebnis Task<searchDataResponse[]>, erhalten searchDataResponse[] und Sie alle scheitern/pass Details haben.

auszupacken es mehr Möglichkeiten für ein ASP.Net Projekt sind:

  • Sprechen Sie die komplette Call-Kette Async und es wird das schließlich das Ergebnis auspacken in dem obersten Anrufer

automatisch auspacken Für Konsolen-Anwendung verwenden Sie etwas wie:

searchDataResponse [] results = Task.WhenAll(<returned searchDataResponse taskList>).ConfigureAwait(false).GetAwaiter().GetResult(); 
+0

Ja, die Details rund um Async-erwarten werden von mir nicht gut verstanden - der Grund für meine Frage. Ich schätze deine Eingabe. Vielen Dank für die Klärung von Task.WaitAll vs. Task.WhenAll. Ich möchte die richtigen Tools verwenden, kenne aber die Unterschiede nicht, daher sind diese Details besonders hilfreich. Außerdem ist es offensichtlich, dass Sie mein Ziel verstehen und nicht auf die Semantik meiner Wortwahl verzichten. Sie haben Recht, ich habe das Schema für searchDataResponse nicht eingefügt - ich versuche, die Frage kurz zu halten. Ich kann den Rückgabetyp nicht ändern, da es sich um einen vom Anbieter bereitgestellten Webdienst handelt. – barrypicker

+0

In diesem Fall ist die einzige Option, die Sie haben, die akzeptierte Lösung, wo Sie über Wrapper erfahren über die fehlgeschlagenen Tasks, aber immer noch verwenden "Task.WhenAll", die viel besser als "Task.WaitAll" für das Async-Design ist –

Verwandte Themen