サーバーに対して約 100 回の http API 呼び出しを行い、結果を処理する必要があるプロセスがあります。コマンドのリストを作成し、それらを非同期で実行するこの commandexecutor をまとめました。約 100 回の呼び出しを行い、結果を解析するには 1 分以上かかります。ブラウザを使用して 1 つのリクエストを送信すると、約 100 ミリ秒で応答が返ってきます。〜 100 回の呼び出しは約 10 秒であると考えるでしょう。私は何か間違ったことをしていると信じており、これはもっと速く進むはずです。
public static class CommandExecutor
{
private static readonly ThreadLocal<List<Command>> CommandsToExecute =
new ThreadLocal<List<Command>>(() => new List<Command>());
private static readonly ThreadLocal<List<Task<List<Candidate>>>> Tasks =
new ThreadLocal<List<Task<List<Candidate>>>>(() => new List<Task<List<Candidate>>>());
public static void ExecuteLater(Command command)
{
CommandsToExecute.Value.Add(command);
}
public static void StartExecuting()
{
foreach (var command in CommandsToExecute.Value)
{
Tasks.Value.Add(Task.Factory.StartNew<List<Candidate>>(command.GetResult));
}
Task.WaitAll(Tasks.Value.ToArray());
}
public static List<Candidate> Result()
{
return Tasks.Value.Where(x => x.Result != null)
.SelectMany(x => x.Result)
.ToList();
}
}
このリストに渡すコマンドは、新しい httpclient を作成し、そのクライアントで URL を使用して getasync を呼び出し、文字列の応答をオブジェクトに変換してから、フィールドをハイドレートします。
protected void Initialize()
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
}
protected override void Execute()
{
Initialize();
var task = _httpClient.GetAsync(string.Format(Url, Input));
Result = ConvertResponseToObjectAsync(task).Result;
Result.ForEach(x => x.prop = value);
}
private static Task<Model> ConvertResponseToObjectAsync(Task<HttpResponseMessage> task)
{
return task.Result.Content.ReadAsAsync<Model>(
new MediaTypeFormatter[]
{
new Formatter()
});
}
私のボトルネックを理解してもらえますか、またはこれをスピードアップする方法について何か提案がありますか?
これらの変更を行う編集により、4秒に短縮されました。
protected override void Execute()
{
Initialize();
_httpClient.GetAsync(string.Format(Url, Input))
.ContinueWith(httpResponse => ConvertResponseToObjectAsync(httpResponse)
.ContinueWith(ProcessResult));
}
protected void ProcessResult(Task<Model> model)
{
Result = model.Result;
Result.ForEach(x => x.prop = value);
}