我正在使用开始/结束编写一个异步库,我需要锁定对象。
目前,我正在使用信号量执行此操作,但调用semaphore.WaitOne()
会挂起调用它的线程。我宁愿使用像 BeginWait 这样的东西,这样它会立即返回并在信号量空闲时调用回调函数。
c#中有这样的对象吗?
我正在使用开始/结束编写一个异步库,我需要锁定对象。
目前,我正在使用信号量执行此操作,但调用semaphore.WaitOne()
会挂起调用它的线程。我宁愿使用像 BeginWait 这样的东西,这样它会立即返回并在信号量空闲时调用回调函数。
c#中有这样的对象吗?
您可以使用(.NET 4.5+)的WaitAsync
方法SemaphoreSlim
来获得一个Task
将在信号量下一次可用时完成的。您可以向该任务添加一个延续,以便在信号量处于活动状态时调用回调。
实际上,这就是我最终得到的结果-也许有人会发现它很有用:
class AsyncSemaphore
{
public AsyncSemaphore(int counter, int maxCounter)
{
this.maxCounter = maxCounter;
this.counter = counter;
}
private int maxCounter, counter;
class CallbackObject:IAsyncResult
{
private AsyncCallback callback;
#region IAsyncResult Members
public object AsyncState { get; set; }
public System.Threading.WaitHandle AsyncWaitHandle
{
get
{
throw new NotImplementedException();
}
}
public bool CompletedSynchronously { get; set; }
public bool IsCompleted { get; set; }
public AsyncCallback Callback
{
get { return callback; }
set { callback = value; }
}
#endregion
}
private ConcurrentQueue<CallbackObject> queue = new ConcurrentQueue<CallbackObject>();
public IAsyncResult BeginWait(AsyncCallback callback, object state)
{
if (callback==null)
{
throw new ArgumentNullException("callback","callback cannot be null");
}
var o=new CallbackObject();
o.AsyncState = state;
o.Callback = callback;
bool execute = false;
if (Interlocked.Decrement(ref this.counter)>=0)
{
o.CompletedSynchronously= execute = true;
}
else
{
queue.Enqueue(o);
}
if (execute)
{
callback(o);
o.IsCompleted = true;
}
return o;
}
public void EndWait(IAsyncResult r)
{}
public void Release()
{
CallbackObject execute = null;
if (Interlocked.Increment(ref this.counter)<1)
{
if (!queue.TryDequeue(out execute))
{
throw new NotImplementedException("ConcurrentQueue.TryDequeue failed");
}
}
else
{
if (counter > maxCounter)
{
throw new SemaphoreFullException("Release was called too many times");
}
}
if (execute!=null)
{
execute.Callback(execute);
execute.IsCompleted = true;
}
}
}