ContinueWith가 작동하는 방법과 혼동 스럽지만 ThreadPool을 차단하고 작업을 순차적으로 실행합니다. 필자가 작성한 다음 코드 예제를 사용하십시오.ContinueWith가 순차적으로 작업을 차단 및/또는 실행하는 것 같습니다.
var items = new List<int>();
for (int i = 0; i < 100; i++)
{
items.Add(i);
}
Parallel.ForEach(items, item =>
{
Task.Factory.StartNew(() =>
{
}).ContinueWith(t =>
{
if (item < 50)
{
System.Console.WriteLine("Blocking in {0}", item.ToString());
var x = SomeLongRunningDatabaseCall(10001);
}
System.Console.WriteLine("Item {0}", item);
});
});
코드 목적은 프로덕션 응용 프로그램에서 의심되는 스레드 차단 문제를 미러링하는 것이 었습니다. 위의 코드로 놀랍게도 ContinueWith를 사용하여 문제가있는 것으로 나타났습니다. 흥미로운 점은 ContinueWith에서 TaskContinuationOptions.LongRunning 옵션을 설정하면 차단하지 않고 작업을 비동기 적으로 실행한다는 것입니다. 또한 프로덕션 앱에서이 작업을 수행 했으므로 문제가 해결되었습니다.
그러나 난 정말 혼란스럽고, TaskContinuationOptions.LongRunning 옵션이없는 ContinueWith 문이 작업을 차단하거나 순차적으로 실행되는 것처럼 보이는 이유에 대해 더 잘 이해하고 싶습니다. 항목 반복마다 새 스레드를 호출하고 있습니다. . 내가 생각할 수있는 유일한 것은 ContinueWith가 선행 작업이 실행 된 스레드에서 실행되고 있지 않지만 블록을 일으킬 수있는 주 스레드에서 실행되고 있다는 것입니다.
도움이나 조언을 주시면 감사하겠습니다.
업데이트
또한 흥미로운 것은 내가
Thread.Sleep(600000)
처럼 뭔가
SomeLongRunningDatabaseCall(10001)
를 교체 할 경우 그것이 수행하는 데이터베이스에 있지만 이후 호출하지만 차단하지 않는다는 것입니다 그것은 자신의 스레드에서 실행 중이다. 적어도 50 이상의 타스크는 데이터베이스를 호출하지 않으므로 다른 타스크는 막히지 않아야한다.
'ContinueWith'에 대한 호출이 거의 확실하게 차단되지 않습니다. 실제 작업은 순차적으로 실행될 수 있습니다. 그들이 존재한다면, 그것이 계속하고있는 것의 본성에 의한 것이지,'ContinueWith'의 구현 방법이 아닙니다. 그래서'Sleep' 호출이 병렬 처리되는 것을 볼 수 있습니다. – Servy
@Servy 아, 무슨 뜻인지 알 겠어.다른 작업이 별도의 스레드에서 실행되고 있다고 생각할 때까지 작업> 50이 실행되지 않는다는 사실을 어떻게 설명 할 수 있습니까? (내 업데이트를 볼 수있는 기회가 있었는지 모르겠다.) –
그저 일부 작업이 다른 작업을 기다리고있는 것 같습니다. 무한 병렬성을 가질 수는 없습니다. 필자는 병렬 DB 호출 수가 50 개를 초과 할 수 없다는 사실에 놀라지 않으며 병렬 실행에서 성능상의 이점도 기대할 수 없습니다. – Servy