Reputation: 8242
i need some help with ConcurrentQueue's and the BlockingCollection.
The scenario is im trying to throttle requests and conform to a 1 request per second limit, the throttling will occur when i dequeue an item from the queue. The application is a MVC 4 app, so there potentially can be multiple producers at any given time, and there is only one consumer/web service i am contacting.
GetUser(string url)
will add a Request to the queue, a
request is just a url.In short i would like to process an item in the queue, download the response and send it back to the calling method. Sending it back to the calling method is where im stuck. What options do i have here?
//I want to do something like this, and wait for the throttled response to return
public class WebService()
{
public string GetUser(string name)
{
var url = buildUrl(name);
var response = string.Empty;
var downloadTask = Task.Factory.StartNew( () => {
response = WebServiceHelper.ThrottledDownload(url);
});
downloadTask.Wait();
return response;
}
}
public static class WebServiceHelper()
{
private static BlockingCollection<Request> requests = new BlockingCollection<Request>();
static WebServiceHelper()
{
foreach(var item in requests.GetEnumerableConsumer()) {
string response = DoWork(item.Url);
//How can i send this back to the calling method?
}
}
public static string ThrottledDownload(string url)
{
//Add the request to the blocking queue
requests.Add(new Request(url, someId));
//How do i get the result of the DoWork method?
}
}
Upvotes: 2
Views: 1283
Reputation: 134005
You probably don't want to "return a result" to the ThrottledDown
method. At least, I wouldn't think so. If you did want to do that, you'd have to make some kind of blocking call. Or use a Task
with continuation ... perhaps async
in C# 5.
It's still unclear what the main thread is doing. I assume it's queuing a bunch of requests that the consumer thread processes at one-second intervals (presumably to prevent you from being throttled by the server that you're querying). You then want the main thread (or something) to be notified so that it can ... do something.
The flow of your program is still unclear.
Depending on what you want the main thread to do (and what information you want it to do that with), you have a number of options. You can:
BlockingCollection
of results. When the consumer completes a request, it adds an object to that collection. The main thread polls that collection to get notification of request completions.ManualResetEventSlim
, for example) to each of your Request
objects. The consumer calls Set
on that event when it's completed the request. The main thread either waits on that event, or polls it periodically.Request
object that you add to the queue). That callback function can notify the main thread, log the result, or whatever you like.Again, without more information about your application and the higher level problem you're trying to solve, it's rather difficult to make more specific recommendations.
Upvotes: 1