2014-11-14 5 views
0

Parallel.ForEach을 사용하여 두 가지 작업을 실행해야하지만 첫 번째 작업을 완료하고 다음에 두 번째 작업을 시작해야합니다. 코드 업데이트 및 마지막으로 업데이트 된 레코드에 대한 Task2 검사 (에서 사람들을 필요로하는 DB에 일부 레코드에 대한병렬 foreach 흐름 제어

Task1 검사 꽤 큰 그대로

Parallel.Foreach(items, (item, state) => 
{ 
    Task1(item); 
    Task2(item); 
} 
public void Task1(Item item) 
{ 
    var records = GetRecordsToExport(); 
    UpdateFields1(records); 
} 
public void Task2(Item item) 
{ 
    var content = File.Read(...); 
    // read every line in content, and for every line update field DB 
    foreach(var c in content) 
    { 
     UpdateFields2(c); // different methods 
    } 
} 

이 코드는, 내가 더 게시 할 수 없습니다 Task1)을 선택하고 다시 업데이트합니다.

처음에는 프로그램이 충돌하는 이유를 찾을 수 없었습니다. 하나의 타스크가 다른 타스크가 완료되기 전에 시작 되었기 때.에 동일한 타스크 테이블에서 작동하기 때.입니다. 실행 순서를 어떻게 제어 할 수 있습니까?

+4

당신이 이해가되지 않습니다 말하고있다. 'Task1'과'Task2'는 같은'item'에 대해 동시에 실행되지 않습니다. 작성한대로 'Task2'는 항상'Task1' 다음에 실행됩니다. 가장 큰 문제는'Task1'과'Task2'의 코드가 threadsafe가 아니라는 것입니다. 'Parallel.ForEach'를 사용하면 * 많은 *'Task1'과'Task2'가 동시에 실행되고 각각 다른 'item'에 대해 실행됩니다. 'Task1'과'Task2'에 대한 코드를 보여줘야합니다. –

+0

글쎄, 당신이 말하는 것은 사실이 아닙니다. Task1은 업데이트해야 할 DB에 대한 일부 레코드를 확인하고 Task2는 마지막으로 업데이트 된 레코드를 확인하고 다시 업데이트합니다. task1과 task2가 동일한 레코드에서 작동하고 task1에서 거의 발생하고 task2가 시작될 때 문제가 발생했습니다. 백그라운드에서 실행하려면 여러 작업이 필요합니다. 예를 들어 모든 작업 1, 모든 작업 2 ... 그러나 모든 작업에 대한 foreach는 필요하지 않습니다. – raresm

+0

내부적으로'Task1'과'Task2'에 대한 새로운 스레드를 돌리고 있습니까? 두 가지 모두에 대한 코드를 추가하십시오. –

답변

0

Task1에서 실행중인 스레드가있는 동안 수행 할 수있는 작업은 Task2에 대한 액세스를 차단하는 것입니다. 그리고 다른 방법으로 Task2가 실행 중일 때 Task1을 입력 할 수있는 스레드가 없습니다.

var lock = new ReaderWriterLockSlim(); 


Parallel.Foreach(items, (item, state) => 
{ 
    lock.EnterReadLock(); 
    try { 
     Task1(item); 
    } finally { 
     lock.ExitReadLock() 
    } 
    lock.EnterWriteLock(); 
    try { 
     Task2(item); 
    } finally { 
     lock.ExitWriteLock() 
    } 
} 

또한 어떤 Task2 방법을 방지 할 수 있습니다이 코드는 두 번 입력해야합니다 :

나는 당신이 ReaderWriterLockSlim 사용하려고 할 수 있다고 생각합니다. 필요한 경우 세마포 또는 뮤텍스를 사용해 볼 수 있습니다. 하지만 이렇게하면 더 복잡해질 것입니다. Task2가 작업 1이 아직 처리가 완료되지 않은하는 항목에서 작동하는

+1

Parallel loop는 아무런 차이를 만들지 못할 것 같다. 작업이 수행 될 때까지 다른 스레드를 보유하면 병렬 실행이 수행되지 않습니다. 또는 나는 무엇인가 놓치고 있냐? –

+0

이러한 작업은 AS export1, export2, ..., exportN 및 import1, import2, ..., importN 또는 AS export1, import1, ..., exportN, importN? 두 번째가 필요해. 두 번째라면, 내가 필요한 코드입니다. (내보내기는 task1이고 가져 오기는 task2 임) – raresm

+0

Task1은 여전히 ​​병렬로 수행됩니다. 그리고 그는 Task1과 Task2를 동시에 실행하는 데 문제가있는 것 같습니다. – GvS

0

그것은 불가능합니다

public class Test 
{ 
    private static object syncObj = new object(); 

    public static void Main() 
    { 
     var items = Enumerable.Range(0, 100).ToArray(); 
     Parallel.ForEach(items, (item, state) => 
     { 
      Task2(Task1(item)); 
     }); 
    } 

    static int Task1(int item) 
    { 
     Console.WriteLine("Task 1 : {0}", item); 
     Thread.Sleep(100); 
     return item; 
    } 

    static int Task2(int item) 
    { 
     Console.WriteLine("Task 2 : {0}", item); 
     return item; 
    } 
}