WebベースのAPIにリクエストを送信するコンポーネントがありますが、APIのデータ制限に違反しないように、これらのリクエストを調整する必要があります。つまり、すべての要求は、送信される速度を制御するためにキューを通過する必要がありますが、最大のスループットを達成するために同時に実行できます(実行する必要があります)。各リクエストは、完了した将来のある時点で、呼び出し元のコードにデータを返す必要があります。
データの返送を処理するための優れたモデルを作成するのに苦労しています。
エンキュープロセスとデキュープロセスはバッファの両端にあるため、Iを使用してメソッドからBlockingCollection
aを返すことはできません。その代わりに、フォームのコールバックを含む型を作成します。Task<TResult>
Schedule
RequestItem<TResult>
Action<Task<TResult>>
アイテムがキューからプルされると、開始されたタスクでコールバックを呼び出すことができますが、その時点でジェネリック型パラメーターを失い、リフレクションとあらゆる種類の厄介さを使用したままになります(可能です)。
例えば:
public class RequestScheduler
{
private readonly BlockingCollection<IRequestItem> _queue = new BlockingCollection<IRequestItem>();
public RequestScheduler()
{
this.Start();
}
// This can't return Task<TResult>, so returns void.
// Instead RequestItem is generic but this poses problems when adding to the queue
public void Schedule<TResult>(RequestItem<TResult> request)
{
_queue.Add(request);
}
private void Start()
{
Task.Factory.StartNew(() =>
{
foreach (var item in _queue.GetConsumingEnumerable())
{
// I want to be able to use the original type parameters here
// is there a nice way without reflection?
// ProcessItem submits an HttpWebRequest
Task.Factory.StartNew(() => ProcessItem(item))
.ContinueWith(t => { item.Callback(t); });
}
});
}
public void Stop()
{
_queue.CompleteAdding();
}
}
public class RequestItem<TResult> : IRequestItem
{
public IOperation<TResult> Operation { get; set; }
public Action<Task<TResult>> Callback { get; set; }
}
Task<TResult>
リクエストをバッファリングし続けても、リクエストがバッファからプルされてAPIに送信されたときにクライアントに返すにはどうすればよいですか?