여러 작업을 순서대로 실행하는 일종의 스케줄러 (관련 용어가 아닐 수도 있음)를 구축하려고합니다. 여기 C# 6 작업 및 모든 하위 작업의 전체 완료를 기다리는 중
는 (가난 큐/디큐 메커니즘을 무시하지만, 여기 문제가 아니라 내가 생각하시기 바랍니다) 내 POC 코드편집 : @Theraot
static void Main(string[] args)
{
ProcessingQueue o_q = new ProcessingQueue();
o_q.Enqueue(async() => { await SimulateTaskSequence(1); });
o_q.Enqueue(async() => { await SimulateTaskSequence(2); });
Console.ReadLine();
}
public static async Task SimulateTaskSequence(int taskNbr)
{
Console.WriteLine("T{0} - Working 1sec", taskNbr);
Thread.Sleep(1000);
Console.WriteLine("T{0} - Zzz 1st 1sec", taskNbr);
await Task.Delay(1000);
Console.WriteLine("T{0} - Working 1sec", taskNbr);
Thread.Sleep(1000);
Console.WriteLine("T{0} - Done", taskNbr);
}
public class ProcessingQueue
{
Queue<Action> _Queue = new Queue<Action>();
private bool _stillRunning = false;
public void Enqueue(Action a)
{
lock (_Queue)
{
_Queue.Enqueue(a);
if (_stillRunning == false)
{
StartProcessing();
}
}
}
private void StartProcessing()
{
_stillRunning = true;
Task.Run(async() =>
{
Action a = null;
while (true)
{
lock (_Queue)
{
if (_Queue.Any() == true)
{
a = _Queue.Dequeue();
}
else
{
break;
}
}
await Task.Run(a); //how to wait for all subtasks!!???
}
_stillRunning = false;
});
}
내 문제의 도움 덕분에 첫 번째 작업 (T1)을 기다리는 즉시 두 번째 작업 (T2)이 실행되기 시작합니다.
나는 다음과 같은 출력 얻을 :
T1 - Working 1sec
T1 - Zzz 1st 1sec
T2 - Working 1sec
T2 - Zzz 1st 1sec
T1 - Working 1sec
T1 - Done
T2 - Working 1sec
T2 - Done
을하지만 난 것 기대하고있어 :
T1 - Working 1sec
T1 - Zzz 1st 1sec
T1 - Working 1sec
T1 - Done
T2 - Working 1sec
T2 - Zzz 1st 1sec
T2 - Working 1sec
T2 - Done
나는이 기본 동작 이유를 이해하지만, 나는 그것을 변경해야합니다. 나는 새로운 TaskFactory에서 TaskContinuationOptions와 TaskCreationOptions를 놀고 있었지만 더 좋은 결과는 없었다. 그게 가능합니까?
덕분에 많은 크리스토프
ProcessingQueue 클래스는 이미 ThreadPool입니다. 올바르게 바꾸기 어렵고, ThreadPool이하지 않는 것을 아무것도하지 않습니다. 기다리는 것 이외에는 즉시 잘못되었다. 하지 마. –
@HansPassant OP가 원하는 것은 OP가 추가 된 작업을 순차적으로 완료하기를 원하는 점에서 ThreadPool과 다릅니다. ThreadPool에는 그러한 보장이 없다. 사실 ThreadPool의 아이디어는 다중 스레드를 사용하여 병렬로 작업하는 것이다 (편집 : 물론 스레드를 다시 사용한다). 이제는 이러한 작업을 동기식으로 실행하거나 대기를 위해 스레드를 사용하는 다른 방법을 통해 달성 할 수 있습니다 ... OP는 그 중 하나도 원하지 않습니다. – Theraot
Task 클래스는 매우 잘 조합되어 있으며, 메인 태스크를 시퀀싱하기 위해 ContinueWith와 서브 태스크 완료를 기다리는 WaitAll 만 있으면된다. 쉬운 peasy,하지만 그것은 당신이 자신의 threadpool을 만들 때 볼 수 없게됩니다. –