ConcurrentDictionary 显然无法在 ASP.NET 控制器中工作
ConcurrentDictionary apparently not working in ASP.NET controller
为什么并发字典的行为不像并发字典?
[Route("aaa")]
[HttpPost]
public Outbound Post(Inbound inbound)
{
Outbound outbound = new Outbound();
TaskState taskState = new TaskState();
taskState.state = 0;
TaskState s;
bool rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc == false)
taskDictionary.GetOrAdd(inbound.taskId, taskState);
else
return null;
if (s != null)
return null;
rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc)
{
string m0 = String.Format("POST dictionary count is " + taskDictionary.Count);
_logger.Log(LogLevel.Error, m0);
}
else
return null;
_logger.Log(LogLevel.Error, "POST method is doing long running work.");
long Billion = 1000000000;
// work quantity 5 means about 26 seconds // 30 billion is 215 seconds
for (long i = 0; i < inbound.WorkQuantity * Billion; i++)
;
outbound.Message = "The server did some work.";
outbound.BigObject = Modify(inbound.BigObject);
_logger.Log(LogLevel.Error, "POST finished long running work and will soon remove from the dictionary.");
rc = taskDictionary.Remove(inbound.taskId, out s);
if (rc == false)
return null;
if (s == null)
return null;
_logger.Log(LogLevel.Error, "POST is returning the object.");
return outbound;
}
[Route("bbb")]
[HttpPost]
public TaskState PostState(TaskId taskId)
{
TaskState s;
if (taskDictionary.TryGetValue(taskId, out s))
{
_logger.Log(LogLevel.Error, "POSTSTATE, state is " + s.AsString());
return s;
}
else
{
_logger.Log(LogLevel.Error, "POSTSTATE, state not found, dictionary count is " + taskDictionary.Count);
return null;
}
}
TaskDictionary taskDictionary = new TaskDictionary();
class TaskDictionary : ConcurrentDictionary<TaskId, TaskState>
{
internal bool IncrementState(TaskId taskId)
{
TaskState s;
if (TryGetValue(taskId, out s))
{
s.Increment();
return true;
}
else
return false;
}
}
日志输出是...
12.207 +00:00 [Error] MyController: POST dictionary count is 1
12.322 +00:00 [Error] MyController: POST method is doing long running work.
14.361 +00:00 [Error] MyController: POSTSTATE, state not found, dictionary count is 0
40.452 +00:00 [Error] MyController: POST finished long running work and will soon remove from the dictionary.
40.569 +00:00 [Error] MyController: POST is returning the object.
具体问题是状态信息请求不起作用,因为字典显示为空。
因此,根据您正在执行的日志记录输出,两个 post 请求生成您向我们展示的输出。
你初始化并发字典的方式,就是为什么它在第二个请求上 returns null 的原因。这与应用程序 接收 这些请求的方式有关。对您应用的每个请求都独立于另一个请求。
简单地说;
一个用户 POST 给你的应用。
请求通过中间件管道,最终将到达您的控制器。现在,这是重要的部分,控制器将为这个特定请求 'constructed' 。它将在请求期间存在。这是因为默认情况下,控制器的生命周期是有范围的。所以下一个请求,将构建一个新的控制器,这意味着字典与第一个不同。
因此,为了克服这个范围请求问题,您创建了一个 service that contains the dictionary, register this as a singleton (meaning it will only be constructed once and then it's shared), and use dependency injection 以在控制器中使用它。
为什么并发字典的行为不像并发字典?
[Route("aaa")]
[HttpPost]
public Outbound Post(Inbound inbound)
{
Outbound outbound = new Outbound();
TaskState taskState = new TaskState();
taskState.state = 0;
TaskState s;
bool rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc == false)
taskDictionary.GetOrAdd(inbound.taskId, taskState);
else
return null;
if (s != null)
return null;
rc = taskDictionary.TryGetValue(inbound.taskId, out s);
if (rc)
{
string m0 = String.Format("POST dictionary count is " + taskDictionary.Count);
_logger.Log(LogLevel.Error, m0);
}
else
return null;
_logger.Log(LogLevel.Error, "POST method is doing long running work.");
long Billion = 1000000000;
// work quantity 5 means about 26 seconds // 30 billion is 215 seconds
for (long i = 0; i < inbound.WorkQuantity * Billion; i++)
;
outbound.Message = "The server did some work.";
outbound.BigObject = Modify(inbound.BigObject);
_logger.Log(LogLevel.Error, "POST finished long running work and will soon remove from the dictionary.");
rc = taskDictionary.Remove(inbound.taskId, out s);
if (rc == false)
return null;
if (s == null)
return null;
_logger.Log(LogLevel.Error, "POST is returning the object.");
return outbound;
}
[Route("bbb")]
[HttpPost]
public TaskState PostState(TaskId taskId)
{
TaskState s;
if (taskDictionary.TryGetValue(taskId, out s))
{
_logger.Log(LogLevel.Error, "POSTSTATE, state is " + s.AsString());
return s;
}
else
{
_logger.Log(LogLevel.Error, "POSTSTATE, state not found, dictionary count is " + taskDictionary.Count);
return null;
}
}
TaskDictionary taskDictionary = new TaskDictionary();
class TaskDictionary : ConcurrentDictionary<TaskId, TaskState>
{
internal bool IncrementState(TaskId taskId)
{
TaskState s;
if (TryGetValue(taskId, out s))
{
s.Increment();
return true;
}
else
return false;
}
}
日志输出是...
12.207 +00:00 [Error] MyController: POST dictionary count is 1
12.322 +00:00 [Error] MyController: POST method is doing long running work.
14.361 +00:00 [Error] MyController: POSTSTATE, state not found, dictionary count is 0
40.452 +00:00 [Error] MyController: POST finished long running work and will soon remove from the dictionary.
40.569 +00:00 [Error] MyController: POST is returning the object.
具体问题是状态信息请求不起作用,因为字典显示为空。
因此,根据您正在执行的日志记录输出,两个 post 请求生成您向我们展示的输出。
你初始化并发字典的方式,就是为什么它在第二个请求上 returns null 的原因。这与应用程序 接收 这些请求的方式有关。对您应用的每个请求都独立于另一个请求。
简单地说;
一个用户 POST 给你的应用。 请求通过中间件管道,最终将到达您的控制器。现在,这是重要的部分,控制器将为这个特定请求 'constructed' 。它将在请求期间存在。这是因为默认情况下,控制器的生命周期是有范围的。所以下一个请求,将构建一个新的控制器,这意味着字典与第一个不同。
因此,为了克服这个范围请求问题,您创建了一个 service that contains the dictionary, register this as a singleton (meaning it will only be constructed once and then it's shared), and use dependency injection 以在控制器中使用它。