私はいくつかのタスクを非同期に実行したい、各タスクは、例外をスローするか、安全に終了することができるHTTP要求を実行します。私は、最初のタスクが正常に完了したとき、またはすべてのタスクが失敗したときに完了する必要があります。ご意見をお聞かせください。どのように述語でTask.WhenAny()を実装する
2
A
答えて
0
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;
}
サンプルを使用するため
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;
}
簡単なチェック:
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}");
+2
クイックレスポンスと偉大なエンジニアリングソリューションの皆様に本当にありがとうございます。あなたは私をたくさん助けました。 –
+0
私はちょうど保護者です - あなたは本当に私のメンターに感謝してください(そしてアップアップ!)http://stackoverflow.com/a/38289396/67824;) –
2
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;
}
使用例:これは失敗したタスクの例外を伝播していないこと
var task = await WhenFirst(tasks, t => t.Status == TaskStatus.RanToCompletion);
if (task != null)
var value = await task;
注意(WhenAny
がない場合と同じように)。
非汎用のTask
のバージョンを作成することもできます。
2
任意のタスクを待って、条件が満たされている場合はタスクを返します。そうでなければ、待つべきタスクがなくなるまで、他のタスクを再び待つ。その
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. 述語を使用して一致アルゴリズムを実装するにはどうすればよいですか?
- 2. Jayway実装を使用したJSONpathでの述語のグループ化
- 3. テンプレートテンプレート関数はどのように実装されていますか? (述語版)
- 4. C++ stl述語の実装について
- 5. どのように実装するPushCacheFilter
- 6. グループを使ってech item、outvar、operatorのアクセスをゲートするためのXMLコードの述語をどのように実装すればよいですか?
- 7. 英語のインライン&&はどのように記述しますか?
- 8. どのように式を作成する:セレクタ+述語ですか?
- 9. ハスケルではどのようにm-ary述語とn-ary述語をとり、(m + n)-ary述語を構築できますか?
- 10. Pythonでは、なぜC言語で実装されたモジュールが純粋なPythonモジュールより速く、どのように記述するのですか?
- 11. 異なるタイプに基づいて述語連鎖を実装する
- 12. 述語によるプロローグ分割リスト - 述語の結果をチェックする方法?
- 13. 非同期述語で "Where"をどのように使用できますか?
- 14. インターフェイス記述言語でint []プロパティをどのように表現しますか?あなたはIDLでこのプロパティを実装する方法を
- 15. どのようにonShowCustomViewメソッドを実装するのですか?
- 16. テーマアプリケーションをどのように実装するのですか?
- 17. どのようにasp.net mvcでdatatablesを実装するには?
- 18. 述語クエリの実行中用語
- 19. imagettextとアラビア語:どのようにRTLモードで記述できますか?
- 20. reCaptchaのピラミッド:どのように実装するのですか?
- 21. どのようにPHPでタペストリーシミュレータを実装する
- 22. 関数型プログラミング言語はどのように実装しますか?
- 23. 一致する述語を検索します。述語の述語?
- 24. Oracleトリガ:どのように実装するのですか?
- 25. Struts2タイル - どのように実装するのですか?
- 26. これはどのように実装するのですか?
- 27. List.Exists(述語)のようなLINQメソッド?
- 28. .Netでのワークフローの記述と実装
- 29. はどのように使用するとのfindAll/3メタ述語
- 30. アトム/ 1述語がプロローグでどのように機能しますか?
を自分で試してみて、あなたが遭遇した特定の問題のために頼みます。少なくとも努力を示す。 – CSharpie