ActionBlock에 Post한게 큐에서 대기하다 처리될때까지 await으로 기다린 후 결과를 받는 패턴을 객체화 시킴.
https://gall.dcinside.com/board/view?id=programming&no=2079638
이패턴 맘에 안들어서 다른 남이만든 기능을 찾다가 포기하고 정리함.
public class FuncBlock<I,O> : IDataflowBlock
{
readonly ActionBlock<bag> a;
IDataflowBlock ia => a;
public Task Completion => ia.Completion;
public void Complete() => ia.Complete();
public void Fault(Exception ex) => ia.Fault(ex);
class bag
{
public I input;
public readonly TaskCompletionSource<O> when = new TaskCompletionSource<O>();
public void set(Func<I, O> f) { try { when.SetResult(f(input)); } catch (Exception ex) { when.TrySetException(ex); } }
public async Task set(Func<I, Task<O>> f) { try { when.SetResult(await f(input)); } catch (Exception ex) { when.TrySetException(ex); } }
}
public FuncBlock(Func<I, O> f) => a = new ActionBlock<bag>(b => b.set(f));
public FuncBlock(Func<I, Task<O>> f) => a = new ActionBlock<bag>(b => b.set(f));
public async Task<O> Invoke(I input)
{
var b = new bag { input = input };
if (a.Post(b))
{
var w = b.when.Task;
await Task.WhenAny(w, Completion);
if (w.IsCompleted)
return await w;
}
throw new Exception($"block is {Completion.Status}");
}
}
테스트 안해봐서 버그있어도 몰름
+ 단순 Thread단위의 호출순서를 보장하려면 Task.Run 대신
TaskFactory<int> tf = new TaskFactory<int>(new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
tf.StartNew(() => { /*do something*/ });
일케 하면 tf끼리는 서로 동기적으로 실행되게됨. 근데 그건 Thread단위의 동기를 의미하고 Task단위로는 await걸리는 순간 다 스까짐.
새버전 :
https://gall.dcinside.com/m/csharp/678