A semaphore with beginwait function

五迷三道 提交于 2019-12-11 03:23:58

问题


I'm writing a asynchronous library using begin/end, and I need to lock objects.

Currently, I'm doing this using semaphores, but calling semaphore.WaitOne() suspends the thread where it is called. I'd rather use something like BeginWait so it would return immediately and call the callback function when the semaphore is free.

Is there such an object in c#?


回答1:


You can use the WaitAsync method of SemaphoreSlim (.NET 4.5+) to get a Task that will be completed when the semaphore is next available. You can add a continuation to that task to have a callback that will be called when the semaphore is active.




回答2:


Actually, this is what I ended up with - maybe someone will find it useful:

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;
        }
    }
}


来源:https://stackoverflow.com/questions/18596662/a-semaphore-with-beginwait-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!