C# 等待一个指定的信号量,WaitOne(100)vs WaitOne(0)+;任务延迟(100)

C# 等待一个指定的信号量,WaitOne(100)vs WaitOne(0)+;任务延迟(100),c#,async-await,semaphore,c#-5.0,winrt-async,C#,Async Await,Semaphore,C# 5.0,Winrt Async,我需要访问由两个进程共享的Windows 8.1应用程序中的资源:应用程序本身和后台任务,因此我需要一个命名的信号量,信号量LIM不适用于此,并且由于我在采集和发布之间进行异步工作,我无法使用互斥体 我在PCL中创建了一个类,该类创建了信号量,并允许我以这种方式等待WaitOne方法: public sealed class AsyncSemaphore:IDisposable { Semaphore _semaphore; public AsyncSemaphore(int i

我需要访问由两个进程共享的Windows 8.1应用程序中的资源:应用程序本身和后台任务,因此我需要一个命名的
信号量
信号量LIM
不适用于此,并且由于我在采集和发布之间进行异步工作,我无法使用
互斥体

我在PCL中创建了一个类,该类创建了信号量,并允许我以这种方式等待
WaitOne
方法:

public sealed class AsyncSemaphore:IDisposable
{
    Semaphore _semaphore;
    public AsyncSemaphore(int initialCount, int maximumCount, string name)
    {
        _semaphore = new Semaphore(initialCount, maximumCount, name);
    }

    public IAsyncOperation<bool> WaitOneAsync()
    {
        return AsyncInfo.Run<bool>(cancellationToken => 
            Task.Run(()=>{
                while (!_semaphore.WaitOne(100))
                {
                    Logger.Log("Waiting...");
                    cancellationToken.ThrowIfCancellationRequested();
                }
                return true;
            },cancellationToken));
    }

    public int Release()
    {
        return _semaphore.Release();
    }

    public void Dispose()
    {
        if (_semaphore != null)
        {
            _semaphore.Dispose();
            _semaphore = null;
        }
    }
}
然后我在代码中使用它,如下所示:

public IAsyncOperation<bool> WaitOneAsync()
{
    return AsyncInfo.Run<bool>(async cancellationToken =>
        {
            while (!_semaphore.WaitOne(0))
            {
                Logger.Log("Waiting...");
                await Task.Delay(100, cancellationToken);
            }
            return true;
        });
}
_semaphore= new AsyncSemaphore(1,1,"uniquename");

//....

await _semaphore.WaitOneAsync();
try
{
   //do more async work
}
finally
{
   _semaphore.Release();
}

这是正确的吗?哪一个是最好的并且使用更少的资源?

第一个选项在整个等待过程中保持一个线程,首先是同步等待,然后是忙等待(while循环)。 第二个选项至少在某种程度上是异步的,因为它使用了Task.Delay来等待,然后才求助于繁忙的等待

第二个(异步)选项使用较少的资源,但需要等待整个超时(
100ms
),然后再次检查,而第一个(同步)选项可以在信号量释放时立即输入信号量

异步选项使用的资源比同步版本少,但实际同步速度比同步版本慢。因此,归根结底,您的具体需求是什么,可扩展性还是速度



您可以通过将超时时间从
100ms
降低来进行优化,从而使异步选项越来越接近同步版本。

如果不是信号量lim,那么什么类型是_信号量?它是System.Threading.semaphore,因此我可以使用命名信号量。SemaphoreSlim不允许使用命名的进程,因此它不会在两个不同的进程之间锁定,我添加了一些代码来澄清……不,这是不正确的。WaitOne(100)不像你的替代品那样有100毫秒的最坏情况。@Hans很好的发现!我在写第二个选项时没有注意到这一点。谢谢。@jmservera:在完整的桌面框架上,您可以使用
ThreadPool.RegisterWaitForSingleObject
。但是,在Win8上,您确实需要阻塞线程池线程或轮询。在这两个线程中,我会选择阻止线程池线程。