2013-03-03 1 views
0

큰 작업을 수행하는 몇 가지 방법이 있다고 가정합니다.콜백을 사용하여 여러 작업 대기열

처음에는 얼마나 많은 방법이 있는지 알지 못합니다 (1 일 수 있고 10 일 수 있습니다).

코드 이것은 다음과 같습니다 :이 인터페이스를 구현

public interface IWorker 
{ 
    void DoWork(DataContainer data); 
} 

그리고 여러 클래스를. 그러면 인스턴스 목록이 있습니다.

List<IWorker> workers = new List<IWorker>(); 

이 메서드를 비동기 적으로 실행하려고합니다. 또한 모든 콜백이 실행될 때 콜백이 필요합니다.

커스텀 래퍼를 작성하지 않고이를 수행 할 수있는 방법이 있습니까? ThreadPool, Tasks, Parallel?

필자는 Parrallel 블록 스레드가 작업이 완료 될 때까지 알고 있으므로 미리 계산 된 동작이 아닙니다.

작업을 생성 할 때 매개 변수가없는 메소드가 있어야합니다. 이렇게 보아도 좋지 않습니다.

ThreadPool에서는 QueueUserWorkItem 메서드를 사용할 수 있지만이 메서드를 사용하면 단일 "total-completion"콜백을 얻지 못합니다.

물론 ThreadPool을 사용하여 원하는 기능을 구현하는 자체 랩퍼를 만들 수 있지만 목표는 이와 같이 작성하지 않고이 작업을 수행하는 것입니다.

아무도 도와 줄 수 있습니까? 감사합니다. .

답변

3

TPL 및 Task 클래스를 찾고 있습니다.

List<IWorker> workers = new List<IWorker>(); 
using (CountdownEvent e = new CountdownEvent(workers.Count)) 
{ 
    foreach (IWorker worker in workers) 
    { 
     // Dynamically increment signal count. 
     e.AddCount(); 
     // run work itself on another thread 
     ThreadPool.QueueUserWorkItem(delegate(object state) 
     { 
      try 
      { 
       ((IWorker)state[0]).DoWork((DataContainer)state[1]); 
      } 
      finally 
      { 
       e.Signal(); 
      } 
     }, 
     // pass required parameters for block of work 
     new object[] { worker, dataForWorker }); 
    } 

    // wait for all workers to finish 
    e.Wait(); 
    // run callback code 
} 
+0

네, 괜찮은 것처럼 들리지만 생성자의 작업은 입력 매개 변수가없는 메소드를 기다리고 있습니다. 그리고 나의 방법에는 그런 것이있다. – steavy

+1

@steavy 태스크를 생성 한 후에 스케줄을 지정할 필요가 없기 때문에 태스크에 입력 매개 변수를 제공 할 필요가 없습니다. 다른 작업에서는 태스크 스케줄러가 위임을 제공 할 필요가 없습니다. 대신 값을 직접 전달하는 대신 람다를 사용하여 함수의 매개 변수로 필요한 변수를 닫으십시오. 덕분에 – Servy

+0

. 당신이 Task.WhenAll을 제안하는 첫번째 사람 이었기 때문에 정답으로 표시했습니다 :) – steavy

0

CountdownEvent 클래스에 대한 주요 후보처럼 소리 집계 작업을 얻을 수 Task.WhenAll를 호출 한 후, 각 작업에 대한 Task을 만듭니다. 원하는 작업을 수행하는 많은 작업을 만든 다음 모든 작업을 기다리고 콜백으로 계속 수행하십시오. DoWork 메서드의 비동기 버전을 분리했습니다. 항상 비동기로 호출하려는 경우 반드시 그렇게 할 필요는 없습니다.

public interface IWorker 
{ 
    Task DoWorkAsync(string data); 
    void DoWork(string data); 
} 

public class Worker : IWorker 
{ 
    public Task DoWorkAsync(string data) 
    { 
     return Task.Run(() => DoWork(data)); 
    } 

    public void DoWork(string data) 
    { 
     Console.WriteLine(data); 
     Thread.Sleep(100); 
    } 
} 

public class Runner 
{ 
    public void Callback() 
    { 
     Console.WriteLine("Everything done"); 
    } 

    public void Run() 
    { 
     var workers = new List<IWorker> {new Worker(), new Worker(), new Worker()}; 
     var tasks = workers.Select(t => t.DoWorkAsync("some data")); 

     Task.WhenAll(tasks).ContinueWith(task => Callback()); 

     Console.WriteLine("Waiting"); 
    } 
} 
2

당신은 Task.WhenAll 찾고 :