如何保护可在一个多线程或异步环境中使用资源? [英] How to protect resources that may be used in a multi-threaded or async environment?
问题描述
我的工作所使用的各种消费者的C#API。这个API可以访问共享资源(在做串行通讯我的情况的硬件),这往往会产生一些不同的角色尝试同时使用它。
I am working on a C# API that is used by a variety of consumers. This API provides access to a shared resource (in my case hardware that does serial communication) , that will often have a few different actors trying to use it concurrently.
我的问题是,我的一些消费者会希望在多线程环境中使用此 - 每一个演员都独立工作并尝试使用该资源。一个简单的锁在这里工作得很好。但我的一些消费者将preFER使用异步的await和时间片资源。 (据我所知),这需要一个异步锁产生的时间片返回到其他任务;在锁定阻止将停止这整个主题。
The issue I have is that some of my consumers will want to use this in a multi-threaded environment - each actor works independently and try to use the resource. A simple lock works fine here. But some of my consumers would prefer to use async-await and time-slice the resource. (As I understand it) this requires an asynchronous lock to yield the timeslice back to other tasks; blocking at a lock would halt that whole thread.
和我想象有串行锁充其量unperformant,以及潜在的竞争条件或死锁在最坏的情况。
And I imagine that having serial locks is unperformant at best, and a potential race condition or deadlock at worst.
那么,如何保护这种共享资源在一个共同的codeBase的两个潜在的并发用法?
So how can I protect this shared resource in a common codebase for both potential concurrency usages?
推荐答案
您可以使用<一个href=\"http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim%28v=vs.110%29.aspx\"><$c$c>SemaphoreSlim$c$c>用1作为请求的数目。 SemaphoreSlim
允许使用<一中既有异步
时尚锁定href=\"http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.waitasync%28v=vs.110%29.aspx\"><$c$c>WaitAsync$c$c>和旧的同步方式:
You can use SemaphoreSlim
with 1 as the number of requests. SemaphoreSlim
allows to lock in both an async
fashion using WaitAsync
and the old synchronous way:
await _semphore.WaitAsync()
try
{
... use shared resource.
}
finally
{
_semphore.Release()
}
您也可以编写自己的基于斯蒂芬Toub的伟大后的 AsyncLock 2012/02/12 / 10266988.aspx>建筑异步协调原语,第6部分:AsyncLock 。我做到了我的应用程序,并允许对同一构造同步和异步锁。
You can also write your own AsyncLock
based on Stephen Toub's great post Building Async Coordination Primitives, Part 6: AsyncLock. I did it in my application and allowed for both synchronous and asynchronous locks on the same construct.
用法:
// Async
using (await _asyncLock.LockAsync())
{
... use shared resource.
}
// Synchronous
using (_asyncLock.Lock())
{
... use shared resource.
}
实施
class AsyncLock
{
private readonly Task<IDisposable> _releaserTask;
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private readonly IDisposable _releaser;
public AsyncLock()
{
_releaser = new Releaser(_semaphore);
_releaserTask = Task.FromResult(_releaser);
}
public IDisposable Lock()
{
_semaphore.Wait();
return _releaser;
}
public Task<IDisposable> LockAsync()
{
var waitTask = _semaphore.WaitAsync();
return waitTask.IsCompleted
? _releaserTask
: waitTask.ContinueWith(
(_, releaser) => (IDisposable) releaser,
_releaser,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
private class Releaser : IDisposable
{
private readonly SemaphoreSlim _semaphore;
public Releaser(SemaphoreSlim semaphore)
{
_semaphore = semaphore;
}
public void Dispose()
{
_semaphore.Release();
}
}
}
这篇关于如何保护可在一个多线程或异步环境中使用资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!