dro*_*owa 3 .net c# asynchronous
想象一下有几个任务试图同时使用资源池。池中的单个资源一次只能由特定数量的任务使用;这个数字可以是一个。
在同步环境中,在我看来WaitHandle.WaitAny&Semaphore是必经之路。
var resources = new[] { new Resource(...), new Resource(...) }; // 'Resource' custom class wrapers the resource
var semaphores = new[] { new Semaphore(1, 1), new Semaphore(1, 1) };
...
var index = WaitHandle.WaitAny(semaphores);
try
{
UseResource(resources[index]);
}
finally
{
semaphores[index].Release();
}
Run Code Online (Sandbox Code Playgroud)
但是我们应该在异步环境中做什么?
我通常建议开发人员将“池”逻辑与“使用”逻辑分开。这种分离的一个不错的好处是,只有池逻辑需要同步。
在实际情况下,资源数量是运行时已知的;更确切地说,它将在应用程序初始化(即配置)时进行。
服务器上的每个端口一次只能接受一个客户端,并且每个服务器只有一个可用端口。
因此,您有一组有限的资源,并且每个资源一次只能由一个线程使用。
由于您无法按需创建新资源,因此需要一个信号来知道何时可用。您可以自己执行此操作,也可以使用诸如a之类的内容BufferBlock<T>作为异步就绪队列。
由于每个资源一次只能由一个线程使用,因此我建议使用通用IDisposable技术将资源释放回池中。
将这些放在一起:
public sealed class Pool
{
private readonly BufferBlock<Resource> _block = new BufferBlock<Resource>();
public Pool()
{
_block.Post(new Resource(this, ...));
_block.Post(new Resource(this, ...));
}
public Resource Allocate()
{
return _block.Receive();
}
public Task<Resource> AllocateAsync()
{
return _block.ReceiveAsync();
}
private void Release(Resource resource)
{
_block.Post(resource);
}
public sealed class Resource : IDisposable
{
private readonly Pool _pool;
public Resource(Pool pool, ...)
{
_pool = pool;
...
}
public void Dispose()
{
_pool.Release(this);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
using (var resource = Pool.Allocate())
UseResource(resource);
Run Code Online (Sandbox Code Playgroud)
要么:
using (var resource = await Pool.AllocateAsync())
await UseResourceAsync(resource);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
390 次 |
| 最近记录: |