zu implementieren Ich möchte mehrere Aufgaben asynchron ausführen, jede Aufgabe wird HTTP-Anforderung ausgeführt, die entweder Ausnahme auslösen oder sicher beenden kann. Ich muss beenden, wenn die erste Aufgabe erfolgreich abgeschlossen wurde oder wenn alle Aufgaben fehlgeschlagen sind. bitte Beratung.Wie Task.WhenAny() mit einem Prädikat
Antwort
public static Task<T> GetFirstResult<T>(
ICollection<Func<CancellationToken, Task<T>>> taskFactories,
Predicate<T> predicate) where T : class
{
var tcs = new TaskCompletionSource<T>();
var cts = new CancellationTokenSource();
int completedCount = 0;
// in case you have a lot of tasks you might need to throttle them
//(e.g. so you don't try to send 99999999 requests at the same time)
// see: http://stackoverflow.com/a/25877042/67824
foreach (var taskFactory in taskFactories)
{
taskFactory(cts.Token).ContinueWith(t =>
{
if (t.Exception != null)
{
Console.WriteLine($"Task completed with exception: {t.Exception}");
}
else if (predicate(t.Result))
{
cts.Cancel();
tcs.TrySetResult(t.Result);
}
if (Interlocked.Increment(ref completedCount) == taskFactories.Count)
{
tcs.SetException(new InvalidOperationException("All tasks failed"));
}
}, cts.Token);
}
return tcs.Task;
}
Verwendungsbeispiel:
using System.Net.Http;
var client = new HttpClient();
var response = await GetFirstResult(
new Func<CancellationToken, Task<HttpResponseMessage>>[]
{
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
ct => client.GetAsync("http://microsoft123456.com", ct),
},
rm => rm.IsSuccessStatusCode);
Console.WriteLine($"Successful response: {response}");
Vielen Dank für die schnelle Reaktion und die großartigen technischen Lösungen. Sie haben mir sehr geholfen. –
Ich bin nur der Schützling - du solltest wirklich meinem Mentor danken (und upvote!) Http://stackoverflow.com/a/38289396/67824;) –
public static Task<Task<T>> WhenFirst<T>(IEnumerable<Task<T>> tasks, Func<Task<T>, bool> predicate)
{
if (tasks == null) throw new ArgumentNullException(nameof(tasks));
if (predicate == null) throw new ArgumentNullException(nameof(predicate));
var tasksArray = (tasks as IReadOnlyList<Task<T>>) ?? tasks.ToArray();
if (tasksArray.Count == 0) throw new ArgumentException("Empty task list", nameof(tasks));
if (tasksArray.Any(t => t == null)) throw new ArgumentException("Tasks contains a null reference", nameof(tasks));
var tcs = new TaskCompletionSource<Task<T>>();
var count = tasksArray.Count;
Action<Task<T>> continuation = t =>
{
if (predicate(t))
{
tcs.TrySetResult(t);
}
if (Interlocked.Decrement(ref count) == 0)
{
tcs.TrySetResult(null);
}
};
foreach (var task in tasksArray)
{
task.ContinueWith(continuation);
}
return tcs.Task;
}
Verwendungsbeispiel:
var task = await WhenFirst(tasks, t => t.Status == TaskStatus.RanToCompletion);
if (task != null)
var value = await task;
Beachten Sie, dass dies nicht Ausnahmen gescheiterter Aufgaben ausbreitet (wie WhenAny
nicht).
Sie können auch eine Version für das nicht generische Task
erstellen.
Warten Sie auf eine Aufgabe und geben Sie die Aufgabe zurück, wenn die Bedingung erfüllt ist. Andernfalls warten Sie erneut auf die anderen Aufgaben, bis keine weitere Aufgabe mehr wartet.
public static async Task<Task> WhenAny(IEnumerable<Task> tasks, Predicate<Task> condition)
{
var tasklist = tasks.ToList();
while (tasklist.Count > 0)
{
var task = await Task.WhenAny(tasklist);
if (condition(task))
return task;
tasklist.Remove(task);
}
return null;
}
einfache Prüfung für das
var tasks = new List<Task> {
Task.FromException(new Exception()),
Task.FromException(new Exception()),
Task.FromException(new Exception()),
Task.CompletedTask, };
var completedTask = WhenAny(tasks, t => t.Status == TaskStatus.RanToCompletion).Result;
if (tasks.IndexOf(completedTask) != 3)
throw new Exception("not expected");
- 1. Coredata: Wie ein bestimmtes Objekt mit einem Prädikat
- 2. SWIFT: Wie erstelle ich ein Prädikat mit einem Int-Wert?
- 3. Wie erreicht man python's any() mit einem benutzerdefinierten Prädikat?
- 4. Warum wirft Task.WhenAny keine erwartete TimeoutException?
- 5. Filtering NSDictionary mit Prädikat
- 6. Prädikat mit Prolog
- 7. C# Liste der Aufgaben und mit task.whenAny Leistung
- 8. Python Generatorfunktion mit Prädikat
- 9. Wie NSArray mit Prädikat auf eine Objekteigenschaft
- 10. Kerndaten: Abfrage ObjektIDs in einem Prädikat?
- 11. Oracle Text catsearch mehrere in einem Prädikat
- 12. Kombination + andPredicateWithSubpredicates: und + orPredicateWithSubpredicates: in einem Prädikat
- 13. Methode mit Prädikat als Parameter
- 14. Finden Sie alle ASP.NET-Steuerelemente, die mit einem Prädikat übereinstimmen?
- 15. CollectionUtils in Java mit Prädikat
- 16. Iterieren über ein Enum in einem Prädikat?
- 17. wie takeFirst Element nach einem Prädikat in scala
- 18. Java ObservableList Filterung mit Prädikat mit Strings
- 19. IndexOf Prädikat?
- 20. Ausdruck gegen Prädikat Probleme
- 21. IEnumerable <T>. Enthält mit Prädikat
- 22. C# - Try/Catch mit Prädikat Ausdruck
- 23. Ransack Gem wählen Prädikat und benutzerdefinierte Prädikat Namen
- 24. iOS WindowsAzureMobileService-Framework - Prädikat mit like keyword
- 25. VB.NET-Prädikat-Array Find
- 26. XPath-Prädikat mit der letzten Funktion
- 27. Prolog Prädikat Probleme
- 28. Core Daten Prädikat Datum Vergleich
- 29. Exportieren nach Excel mit Prädikat-Builder
- 30. Funktioniert Spark Prädikat Pushdown mit JDBC?
selbst ausprobieren und fragen Sie nach speziellen Probleme auftreten. Atleast zeigen etwas Anstrengung. – CSharpie