线程也在异常后执行(在调试期间)
我试图在一个线程中向 ArrayList 添加一些值,然后从另一个线程中删除,而不使用任何锁或互斥体。当删除一个 IndexOutOfRangeException
时,会抛出异常,removeThread 应该只停在那里,但事实并非如此!为什么?`
请看下面的代码:
class Program
{
static ArrayList alist = new ArrayList();
static void Main(string[] args)
{
Program p = new Program();
Thread removeThread = new Thread(p.StartRemoval);
Thread addThread = new Thread(p.StartAddition);
addThread.Start();
removeThread.Start();
addThread .Join();
removeThread.Join();
//Console.ReadKey();
}
void StartRemoval()
{
for (int i = 0; i < 100000; i++)
alist.Remove(i); // Exception
}
void StartAddition()
{
for (int i = 0; i < 100000; i++)
alist.Add(i);
}
}
即使在 removeThread
发生异常之后,它也会执行剩余的迭代。你能解释一下为什么吗?
堆栈跟踪:
at System.Collections.ArrayList.RemoveAt(Int32 索引) 在 Program.cs 中的 ConsoleApplication2.Program.StartRemoval() 处:第 34 行 在 System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext,ContextCallback 回调,对象状态) 在以下场景中的 System.Threading.ThreadHelper.ThreadStart()
处
,我得到了堆栈跟踪上方
将断点放置到所有方法的最后一个大括号中。 (main, StartAddition, StartRemoval)
开始调试。
即使发生异常,StartRemoval 也会执行最后一行。
如果您在没有调试的情况下运行它,它会按预期正常工作。但堆栈跟踪是相同的。 Remove
在代码中被调用,但 RemoveAt
在跟踪报告中被跟踪。
谢谢。
I'm trying to add some values to an ArrayList in one thread and remove from another thread without using any lock or mutex. While removing an IndexOutOfRangeException
is thrown and removeThread should stop there only, but it doens't! Why?`
Please look at following code:
class Program
{
static ArrayList alist = new ArrayList();
static void Main(string[] args)
{
Program p = new Program();
Thread removeThread = new Thread(p.StartRemoval);
Thread addThread = new Thread(p.StartAddition);
addThread.Start();
removeThread.Start();
addThread .Join();
removeThread.Join();
//Console.ReadKey();
}
void StartRemoval()
{
for (int i = 0; i < 100000; i++)
alist.Remove(i); // Exception
}
void StartAddition()
{
for (int i = 0; i < 100000; i++)
alist.Add(i);
}
}
Even after exception in removeThread
, it executes for remaining iterations. Can you please explain why?
Stack Trace:
at System.Collections.ArrayList.RemoveAt(Int32 index)
at ConsoleApplication2.Program.StartRemoval() in Program.cs:line 34
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
in following scenerio, i'm getting above stack trace
put breakpoint to last curly brace of all the methods. (main, StartAddition, StartRemoval)
Start debugging.
StartRemoval executes the last line even after exception.
If you run it without debugging it's working as expected and correctly. But the stack trace is same. Remove
is called in code but RemoveAt
is traced in trace report.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
它不会引发异常 ArrayList.Remove 只是抛出 NotSupportedException ,就在
查看 MSDN 链接了解详细信息时,您当前的代码不会执行任何操作来引发异常。
It doesn't throw an exception ArrayList.Remove just throws NotSupportedException and just when
See MSDN link for detail, your current code doesn't do anything to throw an exception.
您在调试期间看到的异常问题可能是代码与二进制文件不同步的结果。我时常看到这一点。这种情况并不经常发生,但我怀疑我们中的许多人多年来至少见过一两次。通常有效的解决方案是从“构建”菜单项中选择“重建解决方案”。
另请注意,此代码的行为通常是不可预测的,因为当文档声明此类型的实例不可用时,您正在从多个线程访问一个对象(即 ArrayList 的实例)。线程安全。
The problem you are seeing with the exception during debugging is probably the result of the code being out of sync with the binaries. I see this from time to time. It does not happen very often, but I suspect many of us have seen at least once or twice over the years. The solution that usually works to is to select Rebuild Solution from the Build menu item.
Also, note that the behavior of this code will be unpredictable in general because you are accessing an object (namely an instance of
ArrayList
) from more than one thread when the documentation states that instances of this type are not thread-safe.该问题似乎是由于线程 t1 依赖于线程 t2 而引起的,但反之则不然。线程 t2 可以愉快地将元素添加到数组列表的末尾,而不必担心容器内的内容(只要 ArrayList 已像您所做的那样正确分配)。
然而,线程 t1 取决于线程 t2 执行的操作。例如,线程 t1 想要从 alist 中删除元素 5,它可能的线程 t2 仍在添加“5”,并且它还不存在于 alist 中,这会导致异常。 t1 然后抛出此异常并完成执行。因为 t2 独立于 t1(如上所述),所以它会继续执行,直到添加了所有元素。
我相信以下内容可以解决这个问题:
如果您可以在 StartT1 中的异常周围放置一个 try catch 并向我们发布您收到的确切异常,这可能有助于缩小到底发生的情况,但我认为上面的情况最有可能。
希望这有帮助。
The issue seems to arise from the fact that thread t1 is dependent on thread t2 but not visa versa. Thread t2 can happily add elements to the end of your array list without worrying what is within the container (so long as the ArrayList has been properly allocated like you have done).
Thread t1 however is dependent on what thread t2 does. Say for example thread t1 wants to remove element 5 from alist, its possible thread t2 is still adding '5' and it doesn't yet exist within alist, this then causes an exception. t1 then throws this exception and finishes execution. Because t2 is independent of t1 (as described above) it carries on its execution until all elements have been added.
I believe the following would get around this issue:
If you could put a try catch arround the exception in StartT1 and post us the exact exception you're getting this might help narrow down exactly whats going on, but I think the above is most likely.
Hope this helps.