Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 信号量lim不';t对并发请求进行排队,但仍允许双重预订_C#_Multithreading_Asp.net Core_Semaphore - Fatal编程技术网

C# 信号量lim不';t对并发请求进行排队,但仍允许双重预订

C# 信号量lim不';t对并发请求进行排队,但仍允许双重预订,c#,multithreading,asp.net-core,semaphore,C#,Multithreading,Asp.net Core,Semaphore,我在使用.NETCore(2.2)中的SemaphoreSlim类时遇到问题,希望有人能提供帮助 我有一个API方法(AddBooking),它将预订添加到数据库中,这个方法包括3个等待的存储库AddAsync()方法,它们将数据添加到3个单独的表中 我在这个类中看到的所有指南/文档的用法都略有不同,但似乎没有一个真正将并发请求排队,从而导致双重预订 单步执行代码时,当请求正在进行时,信号量的CurrentValue从1更改为0,然后在调用Release()后返回1 专用只读信号量lim\u a

我在使用.NETCore(2.2)中的SemaphoreSlim类时遇到问题,希望有人能提供帮助

我有一个API方法(AddBooking),它将预订添加到数据库中,这个方法包括3个等待的存储库AddAsync()方法,它们将数据添加到3个单独的表中

我在这个类中看到的所有指南/文档的用法都略有不同,但似乎没有一个真正将并发请求排队,从而导致双重预订

单步执行代码时,当请求正在进行时,信号量的CurrentValue从1更改为0,然后在调用Release()后返回1

专用只读信号量lim\u asyncLock;
_asyncLock=新信号量LIM(1);//在构造函数中
公共异步任务AddBooking(NewBooking-NewBooking)
{
wait _asyncLock.WaitAsync().configurewait(false);
尝试
{
如果(!在预订时间范围内(新预订))
return new bookingressponse{Result=false,Message=“预订必须在早上6点到晚上8点之间”};
修正每日储蓄(新预订);
var BookingDetails Response=等待创建BookingDetails(新预订);
如果(!bookingDetailsResponse.Result)
返回预订详细信息响应;
var parkingSpaceBookingResponse=等待创建ParkingSpaceBooking(新预订、预订详细信息响应.预订详细信息);
如果(!ParkingSpaceBookInResponse.Result)
返回ParkingSpaceBookInResponse;
wait_unitOfWork.Save();
返回新BookingResponse{Task=“AddBooking”,Result=true,Message=“Booking added successfully”,BookingDetails=bookingDetailsResponse.BookingDetails,parkingspace=parkingspacebookingsponse.parkingspace};
}
捕获(异常)
{
返回新BookingResponse{Task=“AddBooking”,Result=false,Message=$“将预订添加到数据库时出错:{exception}”;
}
最后
{
_asyncLock.Release();
}
}

我对此类的理解是,如果CurrentCount为0,则后续请求将排队,直到信号量被释放,CurrentCount增加到1(从而允许下一个任务通过),但是同时发出请求仍然会导致双重预订。

一切都取决于实例化异步锁的位置和人员。您可能有多个类实例,每个实例都有自己的锁,这使它们看不到其他请求

基本上你会收到一个请求->实例化你的类->获取锁->生成预订

您必须确保在将运行此代码的类的实例之间共享信号量实例


作为提示,在类构造函数中插入一个日志/断点。您可能会看到它被多次实例化(并创建多个信号量)

您应该这样调用它:
\u asyncLock=new SemaphoreSlim(1,1)

因为第一个参数是初始计数,第二个是最大计数。 现在您只提供了一个初始计数,在第一次调用
Release()
之后,您可以无限制地调用它

或者换句话说,第二个参数禁止超过n个并发调用。
第一个参数表示在第一次调用
Release()
之前可以进行多少次调用。

SemaphoreSlim
应该是
static
?谢谢,似乎已经完成了!我读到的关于这个类的内容似乎暗示,如果只提供一个参数,initialCount也可以充当maxCount:/。@Tom我犯了同样的错误。这对我来说很奇怪。我在看SemaphoreSlim源代码,MaxCount的唯一影响是您可以在没有acquire的情况下发布的数量。你确定它能解决你的问题吗@BrunoBelmondo您能否提供一个链接,因为这似乎与我测试信号量LIM实例的方式有关。
private readonly SemaphoreSlim _asyncLock;
_asyncLock = new SemaphoreSlim(1); // in the constructor

public async Task<BookingResponse> AddBooking(NewBooking newBooking)
        {
            await _asyncLock.WaitAsync().ConfigureAwait(false);

            try
            {
                if (!IsWithinBookingTimeframe(newBooking))
                    return new BookingResponse { Result = false, Message = "Bookings must be between 6am and 8pm" };

                AmendIfDayLightSavings(newBooking);

                var bookingDetailsResponse = await CreateBookingDetails(newBooking);
                if (!bookingDetailsResponse.Result)
                    return bookingDetailsResponse;

                var parkingSpaceBookingResponse = await CreateParkingSpaceBooking(newBooking, bookingDetailsResponse.BookingDetails);
                if (!parkingSpaceBookingResponse.Result)
                    return parkingSpaceBookingResponse;

                await _unitOfWork.Save();
                return new BookingResponse { Task = "AddBooking", Result = true, Message = "Booking added successfully", BookingDetails = bookingDetailsResponse.BookingDetails, ParkingSpaces = parkingSpaceBookingResponse.ParkingSpaces };
            }
            catch (Exception exception)
            {
                return new BookingResponse { Task = "AddBooking", Result = false, Message = $"Error adding booking to database: {exception}" };
            }
            finally
            {
                _asyncLock.Release();
            }
        }