C# 等待一个指定的信号量,WaitOne(100)vs WaitOne(0)+;任务延迟(100)
我需要访问由两个进程共享的Windows 8.1应用程序中的资源:应用程序本身和后台任务,因此我需要一个命名的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
信号量
,信号量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上,您确实需要阻塞线程池线程或轮询。在这两个线程中,我会选择阻止线程池线程。