2013-03-26 39 views
1

我需要一些帮助ConcurrentQueue和BlockingCollection。返回调用方法 - BlockingCollection队列项目

该方案是即时尝试调节请求并符合每秒1个请求的限制,当我从队列中取出一个项目时会发生调节。该应用程序是一个MVC 4应用程序,因此在任何时候都有可能有多个生产者,并且我只接触到一个消费者/网络服务。

  • 生产者GetUser(string url)将请求添加到队列中, 请求只是一个网址。
  • 通过执行一些检查以确保它不违反限制来处理BlockingCollection中的第一项。
  • 从消费者处下载回复
  • 然后以某种方式将下载响应返回给调用方法。 ThrottledDownload

总之,我想处理队列中的项目,下载响应并将其发送回调用方法。将它发送回调用方法是im卡住的地方。我在这里有什么选择?

//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? 
    } 
} 
+0

您是否有手动创建工作人员的原因,而不仅仅是使用线程池?通过它的声音,你可以在调用Task.Run的时候完成工作,在这种情况下,你可以通过'Task'上的'ContinueWith'调用来处理结果。 – Servy 2013-03-26 17:56:13

+0

@Servy我需要依次执行工作(Http请求到Web服务),并符合每秒1个请求规则。 Tbh我没有看过ThreadPool,因为我认为线程安全队列在阅读完毕后会是理想的。在实践中,虽然我不知道如何将结果返回到多生产者单一消费者场景中的调用过程 – gdp 2013-03-26 18:02:18

+0

请详细说明(编辑您的问题以提供更多信息)“返回结果”在此表示的含义。我不清楚哪些请求来自哪里,以及在工作完成时要通知哪个进程或线程。 – 2013-03-26 18:56:09

回答

1

您可能不想“返回结果”到ThrottledDown方法。至少,我不这么认为。如果你确实想这样做,你必须做出某种阻止呼叫。或者使用Task继续......也许在C#5中使用async

目前仍不清楚主线程在做什么。我假设它正在排队消费者线程每隔一秒钟处理一堆请求(大概是为了防止您被查询的服务器阻塞)。然后,您需要通知主线程(或其他东西),以便它可以...执行某些操作。

您的程序流程仍不清楚。

根据你希望主线程做什么(以及你希望它做什么信息),你有很多选择。您可以:

  • 创建另一个BlockingCollection结果。当消费者完成请求时,它会向该集合添加一个对象。主线程轮询该集合以获取请求完成的通知。
  • 上面的变体是使用管道。一个线程排队请求。一个线程将请求出队,发出Web请求,然后将结果放入另一个队列。第三个线程处理第二个队列。
  • 向您的每个Request对象添加活动(例如,ManualResetEventSlim)。当消费者完成请求时,消费者在该事件上调用Set。主线程要么等待该事件,要么定期轮询。
  • 让使用者执行回调函数(在编译时定义,或传入您添加到队列中的Request对象)。该回调函数可以通知主线程,记录结果或任何你喜欢的东西。

此外,没有关于您的应用程序和更多的信息,你正在试图解决的更高层次的问题,这是相当难以作出更具体的建议。

+0

感谢您的输入。我认为我做了我的答案目前还不清楚将所有在那里我真的只是想只处理从队列中的项目和一些数据返回到等待的方法的额外信息。 – gdp 2013-03-26 22:31:22