卢西安在这里讨论了一种模式(Tip 3: Wrap events up in Task-returning APIs and await them)。
我试图在一个经常调用的方法上实现它,看起来像下面的设计代码:
public Task BlackBoxAsync()
{
var tcs = new TaskCompletionSource<Object>(); // new'ed up every call
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
DoSomethingStuff();
tcs.SetResult(null);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
我担心每次通话TaskCompletionSource
时都会有新的表现(我只说我每100毫秒调用一次这种方法)。
我当时正考虑使用BufferBlock<T>
,认为每次通话都不会成为新手。所以它看起来像:
private readonly BufferBlock<object> signalDone; // dummy class-level variable, new'ed up once in CTOR
public Task BlackBoxAsync()
{
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
DoSomethingStuff();
signalDone.Post(null);
}
catch(Exception exc) { }
});
return signalDone.ReceiveAsync();
}
调用对象会将其称为:
for (var i=0; i<10000; i++) {
await BlackBoxAsync().ConfigureAwait(false);
}
是否有人对使用BufferBlock<T>
有任何想法?
答案 0 :(得分:5)
无论您采用何种解决方案,如果您希望每次调用此方法时Password for user@SOMETHING.COM:
任务,创建新的await
都是不可避免的,因为任务不可重复使用。最简单的方法是使用Task
。
所以第一个选项是IMO更喜欢使用TaskCompletionSource
(不出所料,creates a new TaskCompletionSource
on ReceiveAsync
)
更重要的是,您的代码似乎只是将工作卸载到BufferBlock
并返回表示该工作的任务。你为什么不使用简单的ThreadPool
?
Task.Run