在生产环境中,我们有类似僵局的行为,我想知道我们是否正确使用了信号量。
在我们的restapi中,代码如下所示:
public async Task<IActionResult> CreateAsync([FromBody] SomeModel someModel)
{
var result = await _someClass.CreateArende(someModel);
return result;
}
public async Task<IActionResult> RegisterAsync([FromBody] SomeModel someModel)
{
var result = await _someClass.RegisterArende(someModel);
return result;
}
我们的API控制器级别没有semphoreslim,但在someClass中看起来像这样:
public class SomeClass {
protected static SemaphoreSlim _semphoreSlimCreateArende = new SemaphoreSlim(1, 1);
public async virtual Task<SomeResponseDto> CreateArende(SomeModel someModel)
{
try
{
await _semphoreSlimCreateArende.WaitAsync();
}
finally
{
try
{
_semphoreSlimCreateArende.Release();
}
catch (Exception)
{
}
}
return new SomeResponseDto()
{
...
};
}
public async virtual Task<SomeResponseDto> RegisterArende(SomeModel someModel)
{
try
{
await _semphoreSlimCreateArende.WaitAsync();
}
finally
{
try
{
_semphoreSlimCreateArende.Release();
}
catch (Exception)
{
}
}
return new SomeResponseDto()
{
...
};
}
}
信号量应该在控制器级别吗?还是应该将控制器的动作更改为不异步?
答案 0 :(得分:1)
这个问题有点脱节,但是让我们尝试一下吧
首先让模式正确
try
{
await _semphoreSlimCreateArende.WaitAsync();
// do your sync work here
}
finally
{
// if this throws you are certainly doing something wrong
_semphoreSlimCreateArende.Release();
}
其次,为此,您应该从键盘上取下键盘
catch (Exception)
{
}
永远不要盲目地吃异常,如果您将它们放在_semphoreSlimCreateArende.Release
上,那么您已经遇到了严重的问题,您必须找出原因
信号量应改为控制器级别吗?
在最有意义的级别使用它们,我的意思是,如果您需要在此处同步一段代码,而不是在13个级别上进行同步。
还是应该将控制器操作更改为不异步?
如果您有asnyc
的工作,请使控制器async
并使其沿堆栈向下传播到您的async
代码
在生产环境中,我们的行为像僵局一样, 想知道我们是否正确使用了信号量。
哇,我们是在谈论数据库死锁,还是上下文死锁。不管怎样,这听起来有点可疑
仅供参考
在基于Web的服务中使用SemaphoreSlim
是一种讨厌的方法。 SemaphoreSlim
适用于自旋锁,不应在任何时间段内被阻塞使用。自旋锁咀嚼处理器,等待释放锁。理想的情况是,在锁被咬得很少的情况下,并且在不会进一步阻塞的情况下使用它们。
如果您正在使代码死锁,那么您需要找出导致死锁的确切原因,如果死锁是基于任务的死锁,那么SemaphoreSlim
不是正确的工具,如果它是非阻塞的种族条件,那么也许可以接受。如果它是数据库死锁,那么您会有更大的问题。