c# - 字典中存在键时出现 KeyNotFound 异常?

标签 c# multithreading asynchronous dictionary keynotfoundexception

我有一个非常冗长的字典,存储了 350 个键,每个键都是 3 个字节的字节数组。该词典用于解释来自自制硬件的传入数据。

在对应用程序进行压力测试时,我遇到了一个奇怪的错误,它告诉我存在 KeyNotFoundException。奇怪的是, key 就在字典里,而我正盯着它看。字典使用了一个特殊的比较器,这可能是问题的原因:

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 );
    }
}

只有当我模拟用户以疯狂的速度按下按钮时才会发生这种情况,这意味着要多次查询字典中的键。

为什么会这样?比较器有问题吗?

编辑

为清楚起见, Controller 异步运行(因为它需要这样才能处理来自多个不同来源的传入数据)。我不想发布 Controller 的所有源代码,因为有很多,而且其中一些是敏感的,但我将发布这两个处理控件初始化的方法和监听传入数据的方法:

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 ) );*/
}

最佳答案

如果您同时/关闭执行读取和写入操作,Dictionary 类本身不是线程安全的。因此,如果大量线程正在快速访问它,您可能会遇到各种有趣的问题。由于您提到只有在您非常快速地执行操作时才会发生这种情况,所以很可能是问题所在。 据我所知,只执行读取而不执行写入不会对 Dictionary 造成任何问题。

如果您使用的是 .NET 4+,则有一个名为 ConcurrentDictionaryDictionary 线程安全版本,专为此类情况而设计。

关于c# - 字典中存在键时出现 KeyNotFound 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30019129/

相关文章:

c# - .Net 从对象创建报告

c# - 名称在注释中使用 cref 时包含无效字符

c# - 在 .NET 中开发在线网络摄像头视频监控系统(实时视频流问题)

c# - XAML 代码 IsChecked 在 ToggleButton 上触发

java - 如果我不能扩展 Thread(因为我已经在扩展另一个类),我如何并行执行语句?

javascript - 为什么 Node.js 中的异步函数不是异步的?

java - 从 Firebase 数据库读取数据时,如何知道访问的每个查询结果?

java - 如何在后台线程中运行无限循环并重新启动它

java - 进化模拟 - 用于计时器事件处理的持久线程

c++ - future 、 promise 和异常(exception)