I have a very verbose dictionary that stores 350 keys, each of which is a byte array of 3 bytes. This dictionary is to interpret incoming data from home-brewed hardware.
In stress-testing an application, I've hit a strange error where it is telling me that there is a KeyNotFoundException
. The strange thing is that the key is present in the dictionary, and I am staring right at it. The dictionary uses a special comparator which could be the reason for the issue:
private static Dictionary<byte[ ], string> PlayerMap =
new Dictionary<byte[ ], string>( new ByteArrayComparator( ) );
public class ByteArrayComparator : IEqualityComparer<byte[ ]> {
public bool Equals( byte[ ] left, byte[ ] right ) {
if ( left == null || right == null )
return left == right;
return left.SequenceEqual( right );
}
public int GetHashCode( byte[ ] Key ) {
if ( Key == null )
throw new ArgumentNullException( "Key" );
return Key.Sum( B => B );
}
}
This only happens when I simulate users pressing buttons at insane speeds, which means that the dictionary is being queried for the key many, many times.
Why is this happening? Is there something wrong with the comparator?
EDIT
For a bit of clarity the controller runs asynchronously (as it needs to in order to be able to handle the incoming data from multiple various sources). I do not want to post all of the source code for the controller as there is quite a bit, and some of it is sensitive, but I will post these two methods which handle the control initialization and method where it listens for incoming data :
private static void Initialize(
string DevicePath,
R3Controller.HIDP_CAPS Capabilities,
R3Controller.HIDD_ATTRIBUTES Attributes ) {
R3Controller.hRead = R3Controller.OpenDevice( DevicePath );
R3Controller.hWrite = R3Controller.OpenDevice( DevicePath );
R3Controller.fsRead = new FileStream( hRead, FileAccess.ReadWrite, Capabilities.OutputReportByteLength, false );
R3Controller.fsWrite = new FileStream( hWrite, FileAccess.ReadWrite, Capabilities.OutputReportByteLength, false );
if ( R3Controller.fsRead.CanRead ) {
R3Controller.barData = new byte[R3Controller.devCapabilities.Value.InputReportByteLength];
if ( R3Controller.fsRead.CanRead )
R3Controller.fsRead.BeginRead( R3Controller.barData, 0, R3Controller.barData.Length,
new AsyncCallback( R3Controller.Listen ), R3Controller.barData );
else
throw new Exception( "R3 Controller Can't Read Incoming Data" );
}
}
private static void Listen( IAsyncResult IAR ) {
R3Controller.fsRead.EndRead( IAR );
if ( R3Controller.fsRead.CanRead )
R3Controller.fsRead.BeginRead( R3Controller.barData, 0, R3Controller.barData.Length,
new AsyncCallback( R3Controller.Listen ), R3Controller.barData );
else
throw new Exception( "R3 Controller Can't Read Incoming Data" );
R3InputEventArgs Args = new R3InputEventArgs( R3Controller.barData );
if ( R3Controller.Locked || R3Controller.LockedControllers.Contains( Args.Controller ) ) {
//Respond to locked presses if necessary...
if ( R3Controller._LockedFeedback != null )
R3Controller._LockedFeedback( null, Args );
/*GetInvocationList( ).ToList( ).ForEach( E => (
E.Clone( ) as EventHandler<R3InputEventArgs> ).BeginInvoke( null, Args, R3Controller.Heard, null ) );*/
} else if ( R3Controller._ButtonPressed != null )
R3Controller._ButtonPressed(null, Args);/*.GetInvocationList( ).ToList( ).ForEach(
E => ( E.Clone( ) as EventHandler<R3InputEventArgs> ).BeginInvoke( null, Args, R3Controller.Heard, null ) );*/
}