我需要实现一个请求vk.com API的库。问题是API每秒只支持3个请求。我希望API是异步的。
重要提示:API应该支持从多个线程安全访问。
我的想法是实现一个名为throttler的类,它允许每秒不超过3个请求并延迟其他请求。
接口如下:
public interface IThrottler : IDisposable
{
Task<TResult> Throttle<TResult>(Func<Task<TResult>> task);
}
使用方法如下:
var audio = await throttler.Throttle(() => api.MyAudio());
var messages = await throttler.Throttle(() => api.ReadMessages());
var audioLyrics = await throttler.Throttle(() => api.AudioLyrics(audioId));
/// Here should be delay because 3 requests executed
var photo = await throttler.Throttle(() => api.MyPhoto());
如何实现节流器(throttler)?
目前我将其实现为一个队列,由后台线程处理。
public Task<TResult> Throttle<TResult>(Func<Task<TResult>> task)
{
/// TaskRequest has method Run() to run task
/// TaskRequest uses TaskCompletionSource to provide new task
/// which is resolved when queue processed til this element.
var request = new TaskRequest<TResult>(task);
requestQueue.Enqueue(request);
return request.ResultTask;
}
这是处理队列的后台线程循环的缩短代码:private void ProcessQueue(object state)
{
while (true)
{
IRequest request;
while (requestQueue.TryDequeue(out request))
{
/// Delay method calculates actual delay value and calls Thread.Sleep()
Delay();
request.Run();
}
}
}
是否可能不使用后台线程来实现这个功能?
TaskScheduler
不能作为解决此问题的方案,因为接受scheduler
参数的Task.Factory.StartNew
方法不理解async
委托。这里是我对此主题的研究。 - Theodor Zoulias