使用ArrayList解决问题 [英] Threading Issue with ArrayList

查看:84
本文介绍了使用ArrayList解决问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在MSDN中查看此页面:

ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist

classsynchronizedtopic2.htm

(或在线:
http://msdn.microsoft.com/library/de...croottopic.asp


我对整个枚举期间锁定一个ArrayList感兴趣,如示例代码中所示的那样
。我的问题是我仍然得到收集

被修改;枚举操作可能不会执行枚举期间来自

的错误消息InvalidOperationException。我毫不怀疑另一个

线程正在我读取它时从列表中删除项目,但是这个页面在

MSDN中让我相信我可以阻止它发生的时候我是

仍在枚举。


我的ArrayList有一个同步的包装器,声明如下:

protected static ArrayList nodes = ArrayList.Synchronized(new ArrayList());


我在列表中使用foreach进行枚举这通常是一个很糟糕的想法,但是在示例代码中,我已将整个

操作包含在lock(nodes.SyncRoot){}中...那么我做错了什么?


提前多谢。

解决方案

感谢您的快速回应和你投入的努力量。我很赞赏它。


我的枚举循环中的代码是通过事件向另一个线程发送消息对象。

另一个线程。此消息对象将由目标

线程解释,并指示目标线程从ArrayList中删除项目。

因此,我的枚举循环间接负责删除集合

列表中的项目(或至少是我试图实现的效果
实现。)


不应该''这可以吗?只是为了确保我正确地委派责任

(确保调用线程不直接负责

删除项目),我暂停了调用线程和目标线程

仍然按照计划在消息对象收到

后执行事件处理。


这些都不是工作线程,它们是套接字服务器中的套接字线程

其中每个线程代表一个连接的客户端。其他一切似乎都是完美的工作,如果我更换foreach,有一个循环,它工作

罚款。但我真的很了解这一点,而不是使用解决方法。


再次感谢您的帮助。


Nicholas Paldino [.NET / C# MVP] QUOT; < mv*@spam.guard.caspershouse.com>写在

消息新闻:eI ************* @ TK2MSFTNGP10.phx.gbl ...

Eric,

如果你锁定SyncRoot属性返回的对象,
那么你应该不能添加/删除对象,直到锁被释放(我已经附加了一个小的控制台应用程序)这表明这是有效的)。因此,我会怀疑你在循环中调用的东西是
修改内容。

你能在循环中显示代码(以及锁定声明
在你的循环之外)。

-
- Nicholas Paldino [.NET / C#MVP]
- mv*@spam.guard.caspershouse.com

" Eric" < EJ ******** @ yahoo.com>在消息中写道
新闻:%2 **************** @ tk2msftngp13.phx.gbl ...

我在看这个MSDN页面在这里:



ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist

classsynchronizedtopic2.htm

(或在线:


http://msdn.microsoft.com/library/de...croottopic。 asp


我感兴趣的是在整个
枚举期间锁定一个ArrayList,因为

显示在示例代码中。我的问题是我还没有


Collection

被修改了;枚举操作可能不会执行枚举期间来自
InvalidOperationException的错误消息。我毫不怀疑



另一个线程正在我读取它时从列表中删除项目,但这个页面在


MSDN让我相信我可以防止这种情况发生,而
我还在枚举。

我的ArrayList有一个同步的包装器声明如下:
protected static ArrayList nodes = ArrayList.Synchronized(new


ArrayList());


我在列表中使用foreach进行枚举这通常是
a非常糟糕的主意,但是在示例代码中,我已将整个
操作包含在lock(nodes.SyncRoot){}中...那么我做错了什么?

非常感谢提前。




其他方法也可以使用还是在

SyncRoot属性上锁定了ArrayList?所有访问ArrayList

并可能添加或删除元素的东西应使用相同的

锁定方法,以确保正确处理锁定。如果你有一个锁定在SyncRoot上的

方法,另一个线程中的另一个方法

只是随意添加或删除元素而不检查

锁定,那么你会遇到问题。


Ryan Gregg


" Eric" < EJ ******** @ yahoo.com>在消息中写道

新闻:OX ************** @ TK2MSFTNGP09.phx.gbl ...

感谢您的快速回复以及你投入的努力量。我非常感激。

我的枚举循环中的代码是通过事件
向另一个线程发送消息对象。此消息对象将由目标线程解释,并指示目标线程从ArrayList中删除项目。
因此,我的枚举循环间接负责从列表中删除集合
项目(或者至少那是我试图实现的效果。)

这不应该没问题吗?只是为了确保我正确地委派责任(确保调用线程不直接负责项目删除),我暂停了调用线程和目标线程
仍然进行在收到消息对象
之后按计划进行事件处理。

这些不是工作线程,它们是套接字服务器中的套接字线程
其中每个线程代表一个连接客户端。其他所有东西似乎都是完美的工作,如果我更换foreach有一个while循环,它的工作原理很好。但我真的很了解这一点,而不是使用解决方法。

再次感谢您的帮助。

Nicholas Paldino [.NET / C#MVP]" < mv*@spam.guard.caspershouse.com>在消息新闻中写了
:eI ************* @ TK2MSFTNGP10.phx.gbl ...

Eric,

如果你锁定SyncRoot属性返回的对象,那么

你应该不能添加/删除对象,直到锁被释放
(我已经

附加了一个显示此工作的小型控制台应用程序)。因此,我怀疑你在循环中调用的东西是


修改

的内容。

可以你在循环中显示代码(以及循环外的锁定语句)。

-
- Nicholas Paldino [.NET / C#MVP]
- mv*@spam.guard.caspershouse.com

" Eric" < EJ ******** @ yahoo.com>在消息中写道
新闻:%2 **************** @ tk2msftngp13.phx.gbl ...

我在看这个MSDN页面在这里:



ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist

classsynchronizedtopic2.htm

(或在线:


http://msdn.microsoft.com/library/de。 ..croottopic.asp


我对在此期间锁定ArrayList感兴趣整个枚举,

as

在示例代码中显示。我的问题是我还没有


Collection

被修改了;枚举操作可能不会执行枚举期间来自InvalidOperationException的错误消息
。我毫不怀疑另一个线程正在读取它们时从列表中删除项目,但

MSDN中的这个页面


让我相信我可以阻止它发生在


我还在枚举。

我的ArrayList有一个同步的包装器,声明如下:
protected static ArrayList nodes = ArrayList。已同步(new


ArrayList());


我在列表中使用foreach进行枚举通常会


是一个非常糟糕的主意,但是在示例代码中,我将整个
操作包含在lock(nodes.SyncRoot){}中...那么我是什么意思做错了吗?

非常感谢。





糟糕!我误解了一些东西。我现在看到了我的错误。目标线程

(接收事件)在收到消息

对象后不会接管。在触发了

事件后,如何才能有一个接收事件的线程?似乎调用线程实际上是直接负责项目删除的(或更多)。我希望保持

线程尽可能隔离,并且只在它们之间发送消息,而不使用真正的消息/队列系统。

对不起,我们很抱歉。我来自Delphi的背景,并试图理解.NET中的线程。

" Eric" < EJ ******** @ yahoo.com>在消息中写道

新闻:OX ************** @ TK2MSFTNGP09.phx.gbl ...

感谢您的快速回复以及你投入的努力量。我非常感激。

我的枚举循环中的代码是通过事件
向另一个线程发送消息对象。此消息对象将由目标线程解释,并指示目标线程从ArrayList中删除项目。
因此,我的枚举循环间接负责从列表中删除集合
项目(或者至少那是我试图实现的效果。)

这不应该没问题吗?只是为了确保我正确地委派责任(确保调用线程不直接负责项目删除),我暂停了调用线程和目标线程
仍然进行在收到消息对象
之后按计划进行事件处理。

这些不是工作线程,它们是套接字服务器中的套接字线程
其中每个线程代表一个连接客户端。其他所有东西似乎都是完美的工作,如果我更换foreach有一个while循环,它的工作原理很好。但我真的很了解这一点而不是使用解决方法。

再次感谢您的帮助。



I''m looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist
classsynchronizedtopic2.htm

(or online here:
http://msdn.microsoft.com/library/de...croottopic.asp)

And I''m interested in locking an ArrayList during the entire enumeration, as
shown in the example code. My problem is that I''m STILL getting "Collection
was modified; enumeration operation may not execute" error messages from
InvalidOperationException during enumeration. I have no doubt that another
thread is removing items from the list as I read them, but this page in the
MSDN leads me to believe that I can prevent that from happening while I''m
still enumerating.

My ArrayList has a synchronized wrapper declared like this:
protected static ArrayList nodes = ArrayList.Synchronized(new ArrayList());

I am enumerating through the list with "foreach" which normally would be a
very bad idea, but as in the example code, I have enclosed the entire
operation in lock (nodes.SyncRoot) { } ... So what am I doing wrong?

Thanks so much in advance.

解决方案

Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to
another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn''t this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn''t directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was
received.

These aren''t worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems to be
working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:eI*************@TK2MSFTNGP10.phx.gbl...

Eric,

If you are locking on the object returned by the SyncRoot property, then you should not be able Add/Remove objects until the lock is released (I''ve
attached a small console app that shows this works). Because of this, I
would suspect that something that you are calling in your loop is modifying the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Eric" <ej********@yahoo.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...

I''m looking at this page in the MSDN right here:


ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist

classsynchronizedtopic2.htm

(or online here:


http://msdn.microsoft.com/library/de...croottopic.asp)


And I''m interested in locking an ArrayList during the entire enumeration, as

shown in the example code. My problem is that I''m STILL getting


"Collection

was modified; enumeration operation may not execute" error messages from
InvalidOperationException during enumeration. I have no doubt that


another thread is removing items from the list as I read them, but this page in


the

MSDN leads me to believe that I can prevent that from happening while I''m still enumerating.

My ArrayList has a synchronized wrapper declared like this:
protected static ArrayList nodes = ArrayList.Synchronized(new


ArrayList());


I am enumerating through the list with "foreach" which normally would be a very bad idea, but as in the example code, I have enclosed the entire
operation in lock (nodes.SyncRoot) { } ... So what am I doing wrong?

Thanks so much in advance.




Are other methods that also make use of the ArrayList locking on the
SyncRoot property as well? Everything that would be accessing the ArrayList
and potentially adding or removing elements from it should be using the same
lock method, to ensure that the lock is properly handled. If you have one
method that is locking on the SyncRoot, and another method in another thread
that is just adding or removing elements at will without checking for the
lock, then you''re going to run into problems.

Ryan Gregg

"Eric" <ej********@yahoo.com> wrote in message
news:OX**************@TK2MSFTNGP09.phx.gbl...

Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn''t this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn''t directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was received.

These aren''t worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems to be working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in message news:eI*************@TK2MSFTNGP10.phx.gbl...

Eric,

If you are locking on the object returned by the SyncRoot property, then

you should not be able Add/Remove objects until the lock is released (I''ve

attached a small console app that shows this works). Because of this, I
would suspect that something that you are calling in your loop is


modifying

the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com
"Eric" <ej********@yahoo.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...

I''m looking at this page in the MSDN right here:


ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist

classsynchronizedtopic2.htm

(or online here:


http://msdn.microsoft.com/library/de...croottopic.asp)


And I''m interested in locking an ArrayList during the entire enumeration,

as

shown in the example code. My problem is that I''m STILL getting


"Collection

was modified; enumeration operation may not execute" error messages from InvalidOperationException during enumeration. I have no doubt that another thread is removing items from the list as I read them, but this page

in the

MSDN leads me to believe that I can prevent that from happening while


I''m still enumerating.

My ArrayList has a synchronized wrapper declared like this:
protected static ArrayList nodes = ArrayList.Synchronized(new


ArrayList());


I am enumerating through the list with "foreach" which normally would

be a very bad idea, but as in the example code, I have enclosed the entire
operation in lock (nodes.SyncRoot) { } ... So what am I doing wrong?

Thanks so much in advance.





Ooops. I misinterpreted something. I see my mistake now. The target thread
(that receives the event) is NOT taking over after it receives the message
object. How can I have a thread that receives an event take over after the
event has been triggered? It appears as if the calling thread is actually
directly responsible for the item removal (and more). I wanted to keep the
threads as isolated as possible and only send messages between them for
signaling without using a true messaging/queue system.

Sorry for the confusion. I am coming from a Delphi background and trying to
understand threads in .NET.
"Eric" <ej********@yahoo.com> wrote in message
news:OX**************@TK2MSFTNGP09.phx.gbl...

Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn''t this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn''t directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was received.

These aren''t worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems to be working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.



这篇关于使用ArrayList解决问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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