Async 동기화 기원 구축, Part 1 AsyncManualResetEvent

6706 단어
전송문: 비동기 프로그래밍 시리즈 디렉터리...
요즘 공부하고 있어요.NET4.5 병렬 작업의 사용에 관하여.'병렬 작업' 은 이전 버전과 유사한 동기화 메커니즘을 보여 주지 않습니다. 이벤트 대기 핸들, 신호량, lock, Reader Writer Lock... 등 동기화 기원 대상을 보여 주지 않지만, 우리는 시내를 따라 프로그래밍 습관을 나타낼 수 있습니다. 그러면 이 일련의 번역은 '병렬 작업' 에 동기화 기원 대상을 봉인하는 것입니다.번역 리소스 Async 및 Await에 대한 FAQ
1. Async 동기화 기원 구축, Part 1 AsyncManualResetEvent
2. Async 동기화 기원 구축, Part 2 AsyncAutoResetEvent
3. Async 동기화 기원 구축, Part 3 AsyncCountdown Event
4. Async 동기화 기원 구축, Part 4 AsyncBarrier
5. Async 동기화 기원 구축, Part 5 AsyncSemaphore
6. Async 동기화 기원 구축, Part 6 AsyncLock
7. Async 동기화 기원 구축, Part 7 AsyncReader WriterLock
 
원본: Async 동기화 기원을 구축합니다.rar
시작: Async 동기화 기원, Part 1 AsyncManualResetEvent
퀘스트 비동기 모드(TAP)는 시작하고 비동기적으로 완성하기를 기다리는 비동기 조작에 관한 것이 아니라, 더욱 요약하면 퀘스트는 각종 사건을 가리키며 당신이 어떤 일이 발생하기를 기다릴 수 있는 조건을 가리킨다.우리는 심지어 간단한 동기화 기원을 구축하기 위해 임무를 사용할 수 있는데, 이러한 동기화 기원은 유사하다.NET 원본에서 제공하는 비 퀘스트 버전이지만, 비동기적으로 완성될 때까지 기다릴 수 있습니다.
루틴 동기화 기원 중 하나: 이벤트 대기 핸들, 존재합니다.NET Framework.ManualResetEvent 및 AutoResetEvent 및.NET 4는 ManualResetEvent의 새로운 최적화 버전인 ManualResetEventSlim입니다.이벤트 대기 핸들은 한 측이 다른 측이 신호를 제공하기를 기다리는 것이다.예를 들어 ManualResetEvent 는 Set () 를 호출한 후에 Reset () 호출이 나타날 때까지 신호를 유지합니다.
TaskCompletionSource 자체는SpinWait 구조와Task의 IsCompleted 속성을 바탕으로 유사한 이벤트 대기 마우스를 실현하는데 Reset () 방법이 부족합니다.
    //   System.Threading.Tasks.Task  ,
    //   Tasks.TaskCompletionSource.Task 。
    public class TaskCompletionSource
    {
        public TaskCompletionSource();

        //   Tasks.TaskCompletionSource   Tasks.Task。
        public Task Task { get; }

        //   Tasks.Task   Tasks.TaskStatus.Canceled 。
        public void SetCanceled();
        public bool TrySetCanceled();

        //   Tasks.Task   Tasks.TaskStatus.Faulted 。
        public void SetException(Exception exception);
        public void SetException(IEnumerable exceptions);
        public bool TrySetException(Exception exception);
        public bool TrySetException(IEnumerable exceptions);

        //   Tasks.Task   TaskStatus.RanToCompletion 。
        public bool TrySetResult(TResult result);
        ……        
    }

TaskCompletionSource는 신호가 없는 것으로 임무를 완성할 수 없기 때문에 이 임무를 기다리는 비동기적인 방법도 완성할 수 없습니다.(Try) Set* 메서드는 대기 작업을 완료하기 위해 작업을 완료 상태로 전환하는 신호로 사용됩니다.따라서 우리는 TaskCompletionSource를 바탕으로 AsyncManualResetEvent를 구축하기 쉽다.부족한 Reset() 기능을 제공합니다.그런 다음 AsyncManualResetEvent를 구축합니다.
이것은 우리가 구축할 목표 유형이다.
public class AsyncManualResetEvent
{ 
    public Task WaitAsync(); 
    public void Set();
    public void Reset(); 
}

Waitasync() 및 Set() 메서드는 TaskCompletionSource 인스턴스 멤버를 직접 캡슐화합니다.
public class AsyncManualResetEvent
{ 
    private volatile TaskCompletionSource m_tcs = new TaskCompletionSource(); 
    public Task WaitAsync() { return m_tcs.Task; } 
    public void Set() { m_tcs.TrySetResult(true); } 
    … 
}

나머지는 Reset () 방법밖에 없습니다.이후 호출된 Waitasync()에서 반환된 Task를 완료하지 못하도록 하는 것이 목표입니다.Task의 최종 상태는 완성 상태(즉, 정상 완성, 취소, 이상)만 있기 때문에 새로운 TaskCompletionSource 실례를 전환해야 합니다.이렇게 하면 여러 개의 라인이 Reset (), Set (), Waitasync () 를 동시에 호출하면 Waitasync () 는 고립된 Task (즉, 우리는 한 라인이 Waitasync () 를 호출해서 완성할 수 없는 Task (이미 Reset () 를 되돌려주고 다른 라인이 새로운Task에서 Set () 를 호출하는 것을 원하지 않는다.이 목적을 달성하기 위해 현재 Task가 완료되면 새로운 Task를 전환하고 이 전환 작업의 원자성을 확보할 것입니다.(물론 이 목표를 실현하는 다른 전략도 있다. 이것은 단지 내가 선택한 특정한 예일 뿐)
참고: 키워드 volatile 및 Interlocked 클래스 사용.
public class AsyncManualResetEvent
{ 
    private volatile TaskCompletionSource m_tcs = new TaskCompletionSource(); 

    public Task WaitAsync() { return m_tcs.Task; } 
    public void Set() { m_tcs.TrySetResult(true); }  
    public void Reset() 
    { 
        while (true) 
        { 
            var tcs = m_tcs; 
            if (!tcs.Task.IsCompleted || 
                Interlocked.CompareExchange(ref m_tcs, new TaskCompletionSource(), tcs) == tcs) 
                return; 
        } 
    } 
}

지금까지 AsyncManualResetEvent가 완료되었습니다.그러나 또 하나의 중요한 잠재적 행동은 기억해야 한다.앞의 글에서 우리는 연장 임무와 그들이 어떻게 동시 집행하는지에 대해 이야기한 적이 있다. 이것은 연장 임무가 임무 완성의 일부분으로 집행되고 같은 라인에서 임무를 동시 완성한다는 것을 의미한다.TaskCompletionSource의 경우 동기화 연장 작업이 (Try)Set* 방법의 일부로 수행된다는 의미로, AsyncManualResetEvent 예에서 연장 작업은 Set() 방법의 일부로 수행된다는 뜻이다.당신의 요구에 따라, 만약 당신이 이런 일이 발생하기를 원하지 않는다면, 대체할 방법이 있다.한 가지 방법은 비동기적으로 (Try) Set* 방법을 실행하고, 작업이 정말로 완성될 때까지 (작업 자체일 뿐, 작업의 연장 작업은 포함되지 않는다) Set () 호출을 차단하는 것이다.Eg:
public void Set() 
{ 
    var tcs = m_tcs;
    Task.Factory.StartNew(s => ((TaskCompletionSource)s).TrySetResult(true), tcs
       , CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); 
    tcs.Task.Wait(); 
}

물론 당신의 요구에 따라 다른 가능한 방법도 있습니다.
 
이것이 바로 이 절에서 말하고자 하는 AsyncManualResetEvent입니다.
전체 소스는 다음과 같습니다.
    public class AsyncManualResetEvent
    {
        private volatile TaskCompletionSource m_tcs = new TaskCompletionSource();

        public Task WaitAsync() { return m_tcs.Task; }

        public void Set()
        {
            var tcs = m_tcs;
            Task.Factory.StartNew(s => ((TaskCompletionSource)s).TrySetResult(true), tcs
               , CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default);
            tcs.Task.Wait();
        }

        public void Reset()
        {
            while (true)
            {
                var tcs = m_tcs;
                //    Task Task。
                if (!tcs.Task.IsCompleted ||
                    Interlocked.CompareExchange(ref m_tcs, new TaskCompletionSource(), tcs) == tcs)
                    return;
            }
        }
    }

다음 섹션에서는 AutoResetEvent async 버전을 구현합니다.
 
권장 읽기:
비동기 프로그래밍: 동기화 기원 대상 (위)
비동기 프로그래밍: 동기화 기원 대상 (하)
 
시청해 주셔서 감사합니다..
원문: Building Async Coordination Primitives, Part 1: AsyncManual Reset Event
작성자: Stephen Toub – MSFT
 
 
 
 

좋은 웹페이지 즐겨찾기