2013-10-20 3 views
2

TestAwaitTaskArrayAsync()는 코드의 여러 위치에서 호출 할 수 있습니다. taskArray의 실행을 잠그고 다음 호출이 taskArray 실행을 시작하기 전에 모든 작업이 완료 될 때까지 비동기 적으로 대기해야합니다. 잠금으로 실행되는 작업 배열 대기 중

private async Task TestAwaitTaskArrayAsync() 
     { 
      Task[] taskArray; 
      lock (_lock_taskArray) 
      { 
       taskArray = new Task[] 
       { 
       Task.Run(() => 
       { 
        SomeMethod1(); 
       }), 
       Task.Run(() => 
       { 
        SomeMethod2(); 
       }) 
       }; 
      } 
      await Task.WhenAll(taskArray); 
     } 

잠금에서 기다리고 있습니다

이 필요한 경우 그래서 AsyncLock를 사용할 수 수 있지만, 간단하게 시도되지 않은 : 여기에 코드입니다. 이 코드는 정확하고 스레드 안전합니까? 나는 Task.WhenAll (taskArray)를 기다리는 지 잘 모르겠다. 대신 AsyncLock을 사용해야합니까?

+0

'taskArray'가 정말로 로컬 변수라면 아무것도 잠글 필요가 없습니다. –

+0

@Stephen Cleary, taskArray는 로컬이지만 SomeMethod1() 및 SomeMethod2()는 많은 변수를 변경하므로 TestAwaitTaskArrayAsync()가 여러 번 동시에 호출되면 결과를 혼합 할 수 있습니다. – as74

+0

그런 경우에, 당신은'ConcurrentExclusiveSchedulerPair' 및/또는 TPL 데이터 플로우 메쉬로보다 나은 해결책을 찾을 수 있습니다. –

답변

7

작업을 생성하는 것이 매우 빠르며 무엇이든 충돌하지 않으므로 사용중인 잠금은 거의 효과가 없습니다. 비동기 설정에서 상호 배타를 수행하는 방법은 SemaphoreSlim 클래스입니다. Task-async 패턴을 지원하는 잠금 장치입니다. 동기 방식으로

SemaphoreSlim sem = new SemaphoreSlim(1); 
    private async Task TestAwaitTaskArrayAsync() 
    { 
     await sem.WaitAsync(); 
     try { 
     Task[] taskArray = new Task[] 
      { 
      Task.Run(() => 
      { 
       SomeMethod1(); 
      }), 
      Task.Run(() => 
      { 
       SomeMethod2(); 
      }) 
      }; 
     } 
     await Task.WhenAll(taskArray); 
     } 
     finally { sem.Release(); } 
    } 

이 더 쉬웠을 것입니다 :

lock (_lock_taskArray) 
Parallel.Invoke(() => SomeMethod1(),() => SomeMethod2()); 

을 완료.

원하는 경우 AsyncLock을 사용할 수도 있습니다. 그러면 잠금을 안전하게 해제하기 위해 using 구조를 사용할 수 있습니다.

+0

질문은 'AsyncLock'에 대해 말하고 있지만 (어느 것이라고 말하지는 않지만) 아마도 그렇게 할 수 있습니다. – svick

+0

또한,'SemaphoreSlim'에는 매개 변수없는 생성자가 없습니다. 나는 당신이 새로운 SemaphoreSlim (1)을 원한다고 생각한다. (물론 필드는 'var'일 수 없습니다.) – svick

+0

@svick AsyncLock에 대한 링크가 추가되었습니다. – as74