Ich habe gerade angefangen, mit Aufgaben zu arbeiten. Wir haben ein System-Setup, das Anfragen/Antworten verwendet. Der Dienst, auf dem die Aufgaben ausgeführt werden, akzeptiert eine Masteranforderung mit einer Liste von Anforderungsobjekten und gibt eine Masterantwort mit einer Liste von Antwortobjekten zurück. So sieht es etwa so ausRelating Aufgabe Ausnahme zu einer Aufgabe <T> Antwort
var MasterRequest = new MasterRequest;
MasterRequest.Requests.Add(new BlueRequest);
MasterRequest.Requests.Add(new RedRequest);
MasterRequest.Requests.Add(new YellowRequest);
Die Anfrage implementiert eine einfache IRequest-Schnittstelle und jede Farbe ist eine konkrete Klasse. Der Dienst hat konkrete Klassen (Anfrageprozessoren) eingerichtet, um jede Anfrage getrennt und gleichzeitig nach einem konkreten Anfrageobjekt bearbeiten zu können. Jede konkrete Klasse auf den Dienst hat eine GetTask Methode mit einer Signatur wie folgt aus:
Task<IResponse> GetTask(IRequest);
{
// some setup stuff
return Task.Factory.StartNew<IResponse>(() =>
{
// do task stuff
return response; // implements IResponse
});
}
Mein Service nimmt die in MasterRequest weitergegeben und erstellt eine Liste von Aufgaben, die von den GetTask Aufruf Aufruf über den konkreten Anfrage Prozessoren aufgeführt. Ich verwende dann eine Parallel.ForEach auf der Liste, um die Aufgaben zu bearbeiten.
// this is what is returned from the service.
// it has a List<IResponse> on it to hold the resposnes
MasterResposne resposne = new MasterResponse();
List<Task<IResponse>> tasks = new List<Task<IResponse>>();
foreach(IRequest req in MasterRequest.Requests)
{
// factory to get the proper request processor
RequestProcessor p = rp.GetProcessor(req);
tasks.add(p.GetTask(req));
}
Parallel.ForEach(tasks, t =>
{
t.Wait();
// check for faulted and cancelled
// this is where I need help
response.Responses.Add(t.Result);
}
Das alles funktioniert super. Aber wenn die Aufgabe eine Ausnahme auslöst, weiß ich nicht, wie ich sie an die spezifische konkrete Anfrage binden kann, die sie ausgelöst hat. Ich muss es wissen, damit ich dem Anrufer eine korrekt aufgebaute Antwort zurückgeben kann.
Mein erster Gedanke war, Task zu Unterklasse, aber das bringt seine eigene Reihe von Problemen, mit denen ich nicht umgehen möchte.
Ich las diesen SO Artikel und es scheint, wie ich so etwas wie dieses
Is this ok to derive from TPL Task to return more details from method?
Ich denke, Reeds zweites Beispiel tun möchte, ist meine Lösung, aber ich kann immer noch nicht sehen, wie die Aufgaben gleichzeitig ausgeführt werden und sein Ich bin in der Lage, Ausnahmen mit der Anfrage zu verknüpfen, so dass ich eine korrekt erstellte Liste von Antworten zurückgeben kann.
Vielen Dank im Voraus.
1) Ich denke, der empfohlene Weg, um eine Aufgabe zu starten, ist Task.Run() 2) Sie können in TaskCompletionSource graben. Hier einige Links, die mir sehr geholfen haben: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming- Muster/Interop mit anderen asynchronen Mustern und Typen # EAP https://scalablenotions.wordpress.com/2015/05/02/tpl-and-async-await-best-practices-for-the-busy -developer/ – Fildor
Vielleicht ist Task.WaitAll() besser als Parallel? – ASpirin
@Fildor das ist ein guter Link. Ich habe einige andere Anforderungen, die mich zwingen, einen benutzerdefinierten Aufgabenplaner zu haben, so dass ich gezwungen bin, den Task.Factory.StarNew-Aufruf zu verwenden. – brian