I have this piece of code where I want to await on a ongoing task if that task was created for the same input. Here is minimal reproduction of what I'm doing.
private static ConcurrentDictionary<int, Task<int>> _tasks = new ConcurrentDictionary<int, Task<int>>();
private readonly ExternalService _service;
public async Task SampleTask(){
var result = await _service.DoSomething();
await Task.Delay(1000) //this task takes some time do finish
return result;
}
public async Task<int> DoTask(int key) {
var task = _tasks.GetOrAdd(key, _ => SampleTask());
var taskResult = await task;
_tasks.TryRemove(key, out task);
return taskResult;
}
I'm writing a test to ensure the same task is awaited when multiple requests want to perform the task at (roughly) the same time. I'm doing that by mocking _service
and counting how many times _service.DoSomething()
is being called. It should be only once if the calls to DoTask(int key)
where made at roughly the same time.
However, the results show me that if I call DoTask(int key)
more than once with a delay between calls of less than 1~2ms, both tasks will create and execute its on instance of SampleTask()
with the second one replacing the first one in the dictionary.
Considering this, can we say that this method is truly thread-safe? Or isn't my problem a case of thread-safety per se?