6

ActionBlock이있는 Receiver 클래스가 있습니다.

public class Receiver<T> : IReceiver<T>
{

  private ActionBlock<T> _receiver;

  public Task<bool> Send(T item) 
  {
     if(_receiver!=null)
        return _receiver.SendAsync(item);

     //Do some other stuff her
  }

  public void Register (Func<T, Task> receiver)
  {
    _receiver = new ActionBlock<T> (receiver);
  }

  //...
}

ActionBlock에 대한 Register-Action은 await-Statement가있는 async-Method입니다.

private static async Task Writer(int num)
{
   Console.WriteLine("start " + num);
   await Task.Delay(500);
   Console.WriteLine("end " + num);
}

이제는 작업 메서드가 끝날 때까지 조건이 설정되어 있으면 독점적 인 동작을 얻기 위해 동 기적으로 대기해야합니다.

var receiver = new Receiver<int>();
receiver.Register((Func<int, Task) Writer);
receiver.Send(5).Wait(); //does not wait the action-await here!

문제는 "기다리는 Task.Delay (500);" 문이 실행되면 "receiver.Post (5) .Wait ();" 더 이상 기다리지 않는다.

여러 변종 (TaskCompletionSource, ContinueWith, ...) 시도했지만 작동하지 않습니다.

누구든지 문제를 해결하는 방법을 알고 있습니까?


  • 코드를 변경하여 코드를 변경할 수 없었습니다._receiver~로TransformBlock다음 행동을 새로운 것에 넣으십시오.ActionBlock, 연결_receiver? - svick
  • 작은 코드 예제를 줄 수 있습니까? 리팩토링이 어떻게 "독점적 인 행위"로 해결되어야하는지 이해할 수 없습니다. 문제. - obi111

1 답변


3

ActionBlock기본적으로 독점적 인 비헤이비어가 적용됩니다 (한 번에 하나의 항목 만 처리됨). "독점적 인 행동"으로 다른 것을 의미한다면,TaskCompletionSource작업이 완료되면 발신자에게 알립니다.

... use ActionBlock<Tuple<int, TaskCompletionSource<object>>> and Receiver<Tuple<int, TaskCompletionSource<object>>>
var receiver = new Receiver<Tuple<int, TaskCompletionSource<object>>>();
receiver.Register((Func<Tuple<int, TaskCompletionSource<object>>, Task) Writer);
var tcs = new TaskCompletionSource<object>();
receiver.Send(Tuple.Create(5, tcs));
tcs.Task.Wait(); // if you must

private static async Task Writer(int num, TaskCompletionSource<object> tcs)
{
  Console.WriteLine("start " + num);
  await Task.Delay(500);
  Console.WriteLine("end " + num);
  tcs.SetResult(null);
}

또는AsyncLock(내 AsyncEx 라이브러리에 포함) :

private static AsyncLock mutex = new AsyncLock();

private static async Task Writer(int num)
{
  using (await mutex.LockAsync())
  {
    Console.WriteLine("start " + num);
    await Task.Delay(500);
    Console.WriteLine("end " + num);
  }
}


  • 네, ActionBlock은 배타적 인 행동을 강요하지만 등록 된 액션이 비동기 적이라면 "실제 배타적"이 아닙니다. 더 이상. 예, 솔루션이 작동해야하지만 해당 작업이 독점 논리의 진입 점이기 때문에 TaskCompletionSource 매개 변수를 추가하지 않아도됩니다. 사용자가 tcs.SetResult를 호출하지 않으면 더 이상 작동하지 않습니다. - obi111
  • 이 경우에는AsyncLock. 코드 샘플에 대한 업데이트 된 답변보기 항목이 처리 완료 시점을 더 이상 알지 못하지만 각 항목은 한 번에 하나씩 처리됩니다 (async처리). - Stephen Cleary
  • ok 나는 그것이 내가 필요로하는 정확하게 것이다라고 생각한다 - 나는 그것을 시험 할 것이다! - obi111

관련된 질문

최근 질문