2013-03-26 2 views
1

ConcurrentQueue 및 BlockingCollection에 대한 도움이 필요합니다.호출 메서드로 돌아 가기 - BlockingCollection 큐 항목

시나리오는 요청을 제한하고 1 초당 한도를 준수하려고 시도 할 때 대기열에서 항목을 dequeue 할 때 제한이 발생합니다. 응용 프로그램은 MVC 4 응용 프로그램이므로 주어진 시간에 여러 제작자가있을 수 있으며 접촉하는 소비자/웹 서비스는 하나뿐입니다.

  • 프로듀서 GetUser(string url)는 요청이 단지 URL입니다, 큐에 요청을 추가합니다.
  • BlockingCollection의 첫 번째 항목을 처리하여 몇 가지 검사를 수행하여 제한을 위반하지 않았는지 확인합니다.
  • 소비자의 응답을 다운로드하십시오.
  • 그런 다음 어떻게 든 다운로드 응답을 호출 메소드에 반환하십시오. ThrottledDownload

간단히 말해서 대기열에서 항목을 처리하고 응답을 다운로드 한 다음 호출하는 방법으로 다시 보내고 싶습니다. 호출 메소드로 다시 보내면 어디서 붙어 있을까요? 여기에 어떤 옵션이 있습니까?

//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

+0

@Servy 순차적으로 작업 (Http 웹 서비스 요청)을 실행하고 초당 요청 1 건의 규칙을 준수해야합니다. 내가 스레드 안전 큐 (thread safe queue)가 그것에 대해 읽은 후에 이상적이라고 생각할 때 나는 ThreadPool을 보았다. 실제로, 멀티 프로듀서 단일 소비자 시나리오에서 결과를 호출 프로세스로 다시 반환하는 방법을 모르겠다. – gdp

+0

"결과 반환"이 의미하는 바를 자세히 (질문을 편집하여 자세히) 제공하십시오. 요청이 어디에서 왔는지, 그리고 작업이 완료되었을 때 알려주고 싶은 프로세스 나 스레드가 무엇인지는 분명하지 않습니다. –

답변

1

당신은 아마 ThrottledDown 방법 "결과를 반환"싶지 않아요. 적어도 나는 그렇게 생각하지 않을 것이다. 그렇게하고 싶다면 방해 전화를해야합니다. 또는 Task을 계속 사용하고 ... 아마도 async을 C# 5에 사용하십시오.

주 스레드가 수행중인 작업은 아직 명확하지 않습니다. 소비자 스레드가 1 초 간격으로 처리한다는 요청이 여러 번 대기하고 있다고 가정합니다 (쿼리하는 서버에 의해 조절되지 않도록). 그런 다음 주 스레드 (또는 무언가)에게 알림을 보내 원하는 작업을 수행 할 수 있습니다.

프로그램의 흐름이 여전히 불분명합니다.

주 스레드에서 수행 할 작업 (원하는 정보)에 따라 다양한 옵션이 있습니다. 할 수 있습니다 :

  • 다른 결과를 BlockingCollection 생성하십시오. 소비자가 요청을 완료하면 해당 컬렉션에 개체를 추가합니다. 메인 스레드는 콜렉션을 폴링하여 요청 완료 알림을받습니다.
  • 위의 변형은 파이프 라인을 사용하는 것입니다. 하나의 스레드가 요청을 큐에 넣습니다. 하나의 스레드가 요청을 대기열에서 제외하고 웹 요청을 작성한 다음 결과를 다른 대기열에 넣습니다. 세 번째 스레드는 두 번째 큐를 처리합니다.
  • Request 개체 각각에 이벤트 (예 : ManualResetEventSlim)를 추가합니다. 소비자가 요청을 완료하면 해당 이벤트에서 Set으로 전화합니다. 주 스레드는 해당 이벤트를 기다리거나 주기적으로 폴링합니다.
  • 소비자가 컴파일 타임에 정의되거나 대기열에 추가하는 Request 객체에 전달되는 콜백 함수를 실행하게합니다. 콜백 함수는 주 스레드에 알리고 결과를 기록 할 수 있습니다.

는 다시, 응용 프로그램에 대한 자세한 내용 및 해결하기 위해 노력하고있는 높은 수준의 문제없이, 그것은 더 구체적인 권고를 오히려 어렵다.

+0

입력 해 주셔서 감사합니다. 나는 내가 단지 큐에서 항목을 처리하고 대기중인 방법으로 일부 데이터를 반환하기를 원할 때 모든 추가 정보를 추가하는 것이 확실하지 않은 것으로 대답 한 것 같아요. – gdp