0
private readonly Dictionary<int, ManualResetEvent> _ack_events = new Dictionary<int, ManualResetEvent>();

private void ACKRecieved(int ackType)
{
    if (!_ack_events.ContainsKey(ackType))
    { 
        _ack_events.Add(ackType, new ManualResetEvent(true)); 
    }
    _ack_events[ackType].Set();
}

OK so here's the issue. Visual Studio throws an exception at the statement:

ack_events.Add(ackType, new ManualResetEvent(true));

How?

The type of ackType is an int so it can't be null and I don't see how new ManualResetEvent(true) could ever possibly evaluate to null either so... What gives? _ack_events is obviously not null either, as it gets initialized during construction.

All I can ask is... wha?

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
KatDevsGames
  • 1,109
  • 10
  • 21
  • 3
    `ManualResetEvent` constructor could throw it. – Vlad DX Oct 27 '15 at 21:39
  • 8
    Please show the full error message including the stack trace. – poke Oct 27 '15 at 21:40
  • 1
    What's inside the constructor for ManualResetEvent? – DavidG Oct 27 '15 at 21:40
  • 1
    @DavidG that's a .NET Framework class – huysentruitw Oct 27 '15 at 21:42
  • 2
    Put a breakpoint right before that `if` statement, hit the breakpoint using a debug session, hover your mouse pointer over `_ack_events`, and tell me what you see. Also, show us the entire stack trace. – Robert Harvey Oct 27 '15 at 21:43
  • 6
    Hello, I managed to reproduce your issue. This is the problem: [How did I get this NullReferenceException error here right after the constructor?](http://stackoverflow.com/questions/1320264/how-did-i-get-this-nullreferenceexception-error-here-right-after-the-constructor) - _"`Dictionary<>.Insert()` will throw a `NullReferenceException` internally if the dictionary instance is modified from another thread during the insert operation."_ – cbr Oct 27 '15 at 21:47
  • Doing `ContainsKey` then some other operation is very inefficient instead use [`TryGetValue`](https://msdn.microsoft.com/en-us/library/bb347013(v=vs.110).aspx), if that returns false then you do your Add. [Here is a example](https://gist.github.com/leftler/096b0ada4926bf9655d1) – Scott Chamberlain Oct 27 '15 at 21:48
  • @cubrr: Wow, that's... counter-intuitive. – Robert Harvey Oct 27 '15 at 21:49
  • 1
    @RobertHarvey That's why there's [`ConcurrentDictionary`](https://msdn.microsoft.com/en-us/library/dd287191%28v=vs.110%29.aspx) for all your concurrent dictionary needs :o) – cbr Oct 27 '15 at 21:49
  • 4
    @RobertHarvey well, if you insist on using a non-threadsafe class from mutliple threads (without locks) that's the kind of things you risk ;) – Lucas Trzesniewski Oct 27 '15 at 21:50
  • 2
    @JoshuaPech - can you confirm that ACKRecieved() is called from multiple threads? – H H Oct 27 '15 at 21:52
  • @HenkHolterman given the name of the function it's 99.999% sure, but if it's not the case I'll reopen the question. – Lucas Trzesniewski Oct 27 '15 at 21:59
  • 1
    @cubrr is absolutely right. Switching in a ConcurrentDictionary sorted the issue straight away. I'd also like to point out that locks would not work in this case. I didn't even attempt locking because I know it would deadlock elsewhere in the code (not shown). – KatDevsGames Oct 27 '15 at 22:01

0 Answers0