Hashtable损坏(.Net bug?) [英] Hashtable corrupted (.Net bug?)

查看:49
本文介绍了Hashtable损坏(.Net bug?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C#程序,其中多个线程将在同一个Hashtable上运行。

这个Hashtable通过使用Hashtable.Synchronized(myHashtable)

方法同步,所以没有在添加,删除或

迭代Hashtable之前,使用了更多的Lock语句。该程序在高工作负载环境中运行。

运行几天后,现在它突然捕获此异常时

插入一对密钥和对象,


stacktrace = System.NullReferenceException:对象引用未设置为对象的

实例。

at Mas.ShortDataTransportService.SdtsMsgKey.Equals( System.Collections.Hashtable.KeyEquals(Object item,Object key)
at System.Collections.Hashtable.Insert(Object key,Object nvalue, Boolean

add)

在System.Collections.Hashtable.Add(对象键,对象值)

在System.Collections.SyncHashtable.Add (对象键,对象值)



Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer(SdtsOutMsgData dataItem)

at Mas.ShortDataTransportService.SdtsManager .HandleSe ndBufferMsg(Int32&

numSent)
Mas.ShortDataTransportService.SdtsManager.Transm的
它()


Mas下的类是我们自己创建的类。确保

插入的键和对象是非空值,否则ArgumentNullException

而不是NullReferenceException。将被抓住。

似乎Hashtable中的一些关键字已经变为Null,但是怎么能发生这种情况呢?因为Hashtable中的一个键永远不能为空,对吧?将

这是一个.Net Bug?

解决方案

Ken< Ke*@discussions.microsoft.com>写道:

我有一个C#程序,其中多个线程将在同一个Hashtable上运行。
这个Hashtable是通过使用Hashtable.Synchronized(myHashtable)
方法同步的,所以没有进一步的在添加,删除或重复哈希表之前使用了锁定语句。




开始时这是一个问题 - 迭代需要锁定

迭代的持续时间,否则在迭代期间可能会插入一个新值

,这会破坏事情。


来自文档for Hashtable.Synchronized:


< quote>

通过集合枚举本质上不是线程安全的

过程。即使集合同步,其他线程也可以修改集合,这会导致枚举器抛出

异常。为了在枚举期间保证线程安全,您可以在整个枚举期间锁定集合,或者捕获由其他线程所做的更改导致的

异常。

< / quote>


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet

如果回复小组,请不要给我发邮件


Hello Ken


从您发布的堆栈跟踪中,我可以看到在Mas.ShortDataTransportService.SdtsMsgKey类的Equals方法中抛出了异常。

。它似乎是你在使用这个类的实例作为哈希表的关键,并且哈希表可以调用Equals和GetHashCode方法。 null引用

可以是SdtsMsgKey的成员之一。


synchronized方法将保护哈希表不被破坏,但是

它不是线程安全的。有一种情况是Jon提到了关于迭代

哈希表,但在这种情况下你会得到一个InvalidOperationException。


还有以下情况:

if(!myHashtable.ContainsKey(myKey))

myHashtable.Add(myKey,myValue);


虽然散列表可能使用synchronized方法同步,

另一个线程可以在调用

ContainsKey和Add之间添加一对相同的键,导致Add抛出ArgumentException,因为你

试图插入一个重复的密钥。


祝你好运,

谢里夫

" Ken" < Ke*@discussions.microsoft.com>在消息中写道

新闻:9F ********************************** @ microsof t.com ...

我有一个C#程序,其中多个线程将在同一个
Hashtable上运行。使用
Hashtable.Synchronized(myHashtable)方法同步此Hashtable,因此在添加,删除或重复Hashtable之前不再使用Lock语句。该程序在高工作负载环境中运行。
运行几天后,当它插入一对密钥和对象时,它突然发现了这个异常,

stacktrace = System。 NullReferenceException:对象引用未设置为对象的实例。
在Mas.ShortDataTransportService.SdtsMsgKey.Equals(Object obj)
在System.Collections.Hashtable.KeyEquals(Object item, Object.Collections.Hashtable.Insert(Object key,Object nvalue,
Boolean add)
在System.Collections.Hashtable.Add(Object key,Object value)
at System.Collections.SyncHashtable.Add(Object key,Object value)

Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer(SdtsOut

MsgData dataItem )在Mas.ShortDataTransportService.SdtsManager.HandleSe ndBufferMsg(Int32&
numSent)
在Mas.ShortDataTransportService.SdtsManager.Transmit()

这里的类下Mas是我们自己创造的课程。确保
插入的键和对象是非空值,否则
ArgumentNullException而不是NullReferenceException将被抓住。
似乎Hashtable中的一些键已经变为Null,但是怎么会发生这种情况呢?因为Hashtable中的一个键永远不能为空,对吧?
这会是一个.Net Bug吗?



嗨Sherif,

感谢您的回复。但是根据这些信息,我仍然无法弄明白这个问题。我的SdtsMsgKey里面没有对象类型,成员要么是
长或字节,所以它们不能为空。但我确实实现了自己的GetHashCode

方法和Equal方法。以下是实现:

///< summary>

///用作特定类型的哈希函数,

/ //适合用于散列算法和数据结构,如

a哈希表。

///说明:

/// ClientID 3字节(左移3字节x 8位)按位-OR

MsgReference 1字节

///使4个字节完全为int。

/ //< / summary>

///< returns>哈希码< / returns>

公共覆盖int GetHashCode()

{

return((int)(ClientID<< 24)|(int)MsgReference);

}


///< summary>

///确定指定的Object是否等于当前的

对象。

///必需用于数据结构,如哈希表。

///< / summary>

///< param name =" obj">< / param>

///< returns>< / returns>

publi c覆盖bool Equals(object obj)

{

SdtsMsgKey key = obj as SdtsMsgKey;


return((this.ClientID == key.ClientID)&&

(this.MsgReference == key.MsgReference));

}


我想强调的一件事是,在程序运行了一段时间后,NullReferenceException发生了

。这是否表明与线程问题有关的这个问题?
问题?但是根据你的描述,如果问题

是由不安全的Hashtable操作引起的,则异常应该是

InvalidOperationException或ArgumentException,但不是

NullReferenceException。从异常跟踪在

Mas.ShortDataTransportService.SdtsMsgKey.Equals(Object obj)中,我仍然怀疑

null对象是指那个关键字以前是插入的,但不是因为我总是在插入一对关键对象之前创建了一个新密钥

,所以要插入的是



SdtsMsgKey key = new SdtsMsgKey();

key.ClientID = dataItem.ClientID;

key.MsgReference = dataItem.MsgReference;


PendingAckMsgs.Add(key,dataItem);


但如果是这样,我觉得很奇怪。 Hashtable中的一个键如何变为空?


感谢您耐心阅读这个长问题。


最好的问候,

Ken

" Sherif ElMetainy"写道:

Hello Ken

从您发布的堆栈跟踪中,我可以看到在Mas的Equals方法中抛出异常.ShortDataTransportService.SdtsMsgKey类。它似乎是你使用这个类的实例作为哈希表的关键,并且哈希表将调用Equals和GetHashCode方法。空引用
可以是SdtsMsgKey的成员之一。

synchronized方法将保护哈希表不被破坏,但它不是线程安全的。有一种情况是Jon提到了迭代哈希表,但在这种情况下你会得到一个InvalidOperationException。

还有以下情况:
if(!myHashtable。 ContainsKey(myKey))
myHashtable.Add(myKey,myValue);

虽然哈希表可以使用synchronized方法同步,但是另一个线程可以添加一对具有相同的方法调用
ContainsKey和Add之间的关键因为你试图插入一个重复键而导致Add抛出一个ArgumentException。

祝你好运,谢里夫

" Ken" < Ke*@discussions.microsoft.com>在消息中写道
新闻:9F ********************************** @ microsof t.com。 ..

我有一个C#程序,其中多个线程将在同一个


Hashtable上运行。

使用
Hashtable.Synchronized(myHashtable)

方法,因此在添加,删除或重复Hashtable之前不再使用Lock语句。该程序在高工作负载环境中运行。
运行几天后,当它插入一对密钥和对象时,它突然发现了这个异常,

stacktrace = System。 NullReferenceException:对象引用未设置为对象的实例。
在Mas.ShortDataTransportService.SdtsMsgKey.Equals(Object obj)
在System.Collections.Hashtable.KeyEquals(Object item,对象键)
在System.Collections.Hashtable.Insert(Object key,Object nvalue,


Boolean

add)
在System.Collections。 Hashtable.Add(对象键,对象值)
在System.Collections.SyncHashtable.Add(对象键,对象值)
at


Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer (SdtsOut
MsgData dataItem)在Mas.Short的Mas.ShortDataTransportService.SdtsManager.HandleSe ndBufferMsg(Int32&
numSent)中的


DataTransportService.SdtsManager.Transmit()

Mas下的类是我们自己创建的类。确保插入的密钥和对象是非空值,否则


ArgumentNullException

而不是NullReferenceException。将被抓住。
似乎Hashtable中的一些键已经变为Null,但是怎么会发生这种情况呢?因为Hashtable中的一个键永远不能为空,对吧?


这是一个.Net Bug?




I have a C# Program where multiple threads will operate on a same Hashtable.
This Hashtable is synchronized by using Hashtable.Synchronized(myHashtable)
method, so no further Lock statements are used before adding, removing or
iterating the Hashtable. The program runs in a high workload environment.
After running a few days, now it suddenly catchs this Exception when
inserting a pair of key and object,

stacktrace = System.NullReferenceException: Object reference not set to an
instance of an object.
at Mas.ShortDataTransportService.SdtsMsgKey.Equals(Ob ject obj)
at System.Collections.Hashtable.KeyEquals(Object item, Object key)
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean
add)
at System.Collections.Hashtable.Add(Object key, Object value)
at System.Collections.SyncHashtable.Add(Object key, Object value)
at
Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer(SdtsOutMsgData dataItem)
at Mas.ShortDataTransportService.SdtsManager.HandleSe ndBufferMsg(Int32&
numSent)
at Mas.ShortDataTransportService.SdtsManager.Transmit ()

Here classes under Mas are our self-created classes. It is sure that the
inserted key and object are non-null value, otherwise "ArgumentNullException"
instead of "NullReferenceException" will be caught.
It seems that some key inside the Hashtable has become Null, but how can
this happen? because a key inside a Hashtable can never be null, right? Will
this be a .Net Bug?

解决方案

Ken <Ke*@discussions.microsoft.com> wrote:

I have a C# Program where multiple threads will operate on a same Hashtable.
This Hashtable is synchronized by using Hashtable.Synchronized(myHashtable)
method, so no further Lock statements are used before adding, removing or
iterating the Hashtable.



That''s a problem to start with - iteration requires a lock for the
duration of the iteration, otherwise a new value could be inserted
during the iteration, which would break things.

From the docs for Hashtable.Synchronized:

<quote>
Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still modify the collection, which causes the enumerator to throw an
exception. To guarantee thread safety during enumeration, you can
either lock the collection during the entire enumeration or catch the
exceptions resulting from changes made by other threads.
</quote>

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


Hello Ken

From the stack trace you posted, I can see that the exception is thrown in
the Equals method of the Mas.ShortDataTransportService.SdtsMsgKey class. It
seems you are using instances of this class as the key to the hashtable, and
the hashtable would call Equals and GetHashCode methods. The null reference
can be one of the members of the SdtsMsgKey.

The synchronized method will protect the hashtable from being corrupted, but
it is not thread safe. There is the case that Jon mentioned about iterating
the hashtable, but you would get an InvalidOperationException in that case.

There is also the following case:
if(!myHashtable.ContainsKey(myKey))
myHashtable.Add(myKey, myValue);

Although the hashtable may be synchronized using the synchronized method,
another thread can add a pair with the same key between the call to
ContainsKey and Add causing Add to throw an ArgumentException because you
are attempting to insert a duplicate key.

Best regards,
Sherif
"Ken" <Ke*@discussions.microsoft.com> wrote in message
news:9F**********************************@microsof t.com...

I have a C# Program where multiple threads will operate on a same Hashtable. This Hashtable is synchronized by using Hashtable.Synchronized(myHashtable) method, so no further Lock statements are used before adding, removing or
iterating the Hashtable. The program runs in a high workload environment.
After running a few days, now it suddenly catchs this Exception when
inserting a pair of key and object,

stacktrace = System.NullReferenceException: Object reference not set to an
instance of an object.
at Mas.ShortDataTransportService.SdtsMsgKey.Equals(Ob ject obj)
at System.Collections.Hashtable.KeyEquals(Object item, Object key)
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at System.Collections.Hashtable.Add(Object key, Object value)
at System.Collections.SyncHashtable.Add(Object key, Object value)
at
Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer(SdtsOut
MsgData dataItem) at Mas.ShortDataTransportService.SdtsManager.HandleSe ndBufferMsg(Int32&
numSent)
at Mas.ShortDataTransportService.SdtsManager.Transmit ()

Here classes under Mas are our self-created classes. It is sure that the
inserted key and object are non-null value, otherwise "ArgumentNullException" instead of "NullReferenceException" will be caught.
It seems that some key inside the Hashtable has become Null, but how can
this happen? because a key inside a Hashtable can never be null, right? Will this be a .Net Bug?



Hi Sherif,
Thank you for your reply. But from the information, I still can''t figure out
the problem. My SdtsMsgKey has no object type inside, the members are either
long or byte, so they can''t be null. But I did implement my own GetHashCode
method and Equal method. Here are the implementation:
/// <summary>
/// Serves as a hash function for a particular type,
/// suitable for use in hashing algorithms and data structures like
a hash table.
/// EXPLANATION:
/// ClientID 3 bytes (shift left 3 bytes x 8 bits) bitwise-OR
MsgReference 1 byte
/// Makes 4 bytes exactly an int.
/// </summary>
/// <returns>Hash code</returns>
public override int GetHashCode()
{
return ((int) (ClientID << 24) | (int) MsgReference);
}

/// <summary>
/// Determines whether the specified Object is equal to the current
Object.
/// Required for use in data structures like a hash table.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
SdtsMsgKey key = obj as SdtsMsgKey;

return ((this.ClientID == key.ClientID) &&
(this.MsgReference == key.MsgReference));
}

One thing I want to emphasize is that the NullReferenceException happens
after the program running for quite some time. Will that indicate this
problem related to threading issue? But from your description, if the problem
is caused by un-safe Hashtable operation, the exception should be
InvalidOperationException or ArgumentException, but not
NullReferenceException. From the exception trace "at
Mas.ShortDataTransportService.SdtsMsgKey.Equals(Ob ject obj)", I still suspect
the null object is referring to the key that is previously inserted, but not
the one that is going to be inserted because I always created a new key
before I insert the pair of key object:

SdtsMsgKey key = new SdtsMsgKey();
key.ClientID = dataItem.ClientID;
key.MsgReference = dataItem.MsgReference;

PendingAckMsgs.Add(key, dataItem);

But if so, I feel very strange. How can a key in a Hashtable become null?

Thank you for your patience to read this long question.

Best Regards,
Ken
"Sherif ElMetainy" wrote:

Hello Ken

From the stack trace you posted, I can see that the exception is thrown in
the Equals method of the Mas.ShortDataTransportService.SdtsMsgKey class. It
seems you are using instances of this class as the key to the hashtable, and
the hashtable would call Equals and GetHashCode methods. The null reference
can be one of the members of the SdtsMsgKey.

The synchronized method will protect the hashtable from being corrupted, but
it is not thread safe. There is the case that Jon mentioned about iterating
the hashtable, but you would get an InvalidOperationException in that case.

There is also the following case:
if(!myHashtable.ContainsKey(myKey))
myHashtable.Add(myKey, myValue);

Although the hashtable may be synchronized using the synchronized method,
another thread can add a pair with the same key between the call to
ContainsKey and Add causing Add to throw an ArgumentException because you
are attempting to insert a duplicate key.

Best regards,
Sherif
"Ken" <Ke*@discussions.microsoft.com> wrote in message
news:9F**********************************@microsof t.com...

I have a C# Program where multiple threads will operate on a same


Hashtable.

This Hashtable is synchronized by using


Hashtable.Synchronized(myHashtable)

method, so no further Lock statements are used before adding, removing or
iterating the Hashtable. The program runs in a high workload environment.
After running a few days, now it suddenly catchs this Exception when
inserting a pair of key and object,

stacktrace = System.NullReferenceException: Object reference not set to an
instance of an object.
at Mas.ShortDataTransportService.SdtsMsgKey.Equals(Ob ject obj)
at System.Collections.Hashtable.KeyEquals(Object item, Object key)
at System.Collections.Hashtable.Insert(Object key, Object nvalue,


Boolean

add)
at System.Collections.Hashtable.Add(Object key, Object value)
at System.Collections.SyncHashtable.Add(Object key, Object value)
at


Mas.ShortDataTransportService.SdtsManager.InsertIn toPendingAckBuffer(SdtsOut
MsgData dataItem)

at Mas.ShortDataTransportService.SdtsManager.HandleSe ndBufferMsg(Int32&
numSent)
at Mas.ShortDataTransportService.SdtsManager.Transmit ()

Here classes under Mas are our self-created classes. It is sure that the
inserted key and object are non-null value, otherwise


"ArgumentNullException"

instead of "NullReferenceException" will be caught.
It seems that some key inside the Hashtable has become Null, but how can
this happen? because a key inside a Hashtable can never be null, right?


Will

this be a .Net Bug?




这篇关于Hashtable损坏(.Net bug?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆