跳过 SemaphoreSlim 而不是等待
Posted
技术标签:
【中文标题】跳过 SemaphoreSlim 而不是等待【英文标题】:Skip SemaphoreSlim instead of wait 【发布时间】:2014-10-07 10:48:03 【问题描述】:我在 Async/Await 函数中有一部分代码,我希望一次只执行一个线程。
通过创建一个新的 SemaphoreSlim(1) 并使用 WaitAsync/Release,这相对简单。效果是第一个线程执行,其他线程等待,然后一个接一个地执行。
我想要达到的效果实际上略有不同。我希望其他线程不要等待,而是从函数中返回(即我不想阻塞其他线程)。因此,如果有一个属性“NumberOfThreadsCurrentlyExecuting”,我实际上会有一个 If Semaphore.NumberOfThreadsCurrentlyExecuting > 0 Then Return。
但是这样的属性不存在。有没有人知道解决这个问题的方法?
谢谢 查尔斯
【问题讨论】:
检查CurrentCount? 对。愚蠢的问题。对不起!我知道 CurrentCount 指的是最大线程数而不是剩余线程数。 并意识到我的错误来自哪里:VS 中 CurrentCount 的工具提示说“获取允许进入 System.Threading.SemaphoreSlim 的线程数”,这是模棱两可的(我解释最大)。 【参考方案1】:Charles,使用具有零超时的SemaphoreSlim.Wait/Async
怎么样?如果不能输入信号量(因为已经输入),则返回false。
请注意Monitor
(因此lock
)完全不适合async
(因此你不能在lock
中使用await
)因为
-
进入锁后,您的任务可能会在另一个线程上继续(因此您将尝试从另一个线程释放锁)
在您等待之后,另一个延续可能会使用您的线程(当它仍然持有锁时),因此如果它尝试获取锁,它将成功
【讨论】:
零超时是我所需要的!如果我的方法无法获取锁/事件/任何东西,我希望我的方法立即退出...... 换句话说:不要在锁/监视器中使用await
。感谢Wait(0)
提示!【参考方案2】:
您可以只使用Monitor
,而不是信号量。
如果调用TryEnter
失败,则另一个线程处于“锁定”状态。
这是线程安全的(不同于检查信号量计数),并且相当简单:
// 使用类似:object sync = new object();
bool lockTaken = Monitor.TryEnter(sync);
try
if (lockTaken)
// You're here - do your work
else
// Something else was in the thread - exit?
return;
finally
if (lockTaken) Monitor.Exit(sync);
【讨论】:
谢谢。这也是个好办法!它适用于异步/等待吗? Await 在 SyncLock 中是不允许的,我原以为这看起来很接近锁。 @Charles 它有效,但非常危险 - 请参阅:***.com/a/7612714/65358 那是我的担心。我假设因为 SemaphoreSlim 有一个 Async WaitAsync 方法,所以在 WaitAsync/Release 之间放置一些等待调用是安全的,但你认为有类似的风险吗? @Charles 如果您尝试在其中等待,任何给您阻塞语义的东西都会遇到同样的问题...阅读该帖子 ;) 现在我不得不对此投反对票——这个问题是关于 async/await 的,而这对于 async/await 并不适用(正如你所指出的)以上是关于跳过 SemaphoreSlim 而不是等待的主要内容,如果未能解决你的问题,请参考以下文章