【发布时间】:2009-09-04 01:39:52
【问题描述】:
我为 .NET 编写了一个多线程应用程序,在非常重要的代码部分中,我有以下内容:
public class ContainerClass {
private object list_lock;
private ArrayList list;
private object init_lock = new object();
private ThreadClass thread;
public void Start() {
lock(init_lock) {
if (thread == null) {
thread = new ThreadClass();
...
}
}
}
public void Stop() {
lock(init_lock) {
if (thread != null) {
thread.processList(0);
thread.finish();
thread.waitUntilFinished();
thread = null;
} else {
throw new ApplicationException("Assertion failed - already stopped.");
}
...
}
}
private class ThreadedClass {
private ContainerClass container;
private Thread thread;
private bool finished;
private bool actually_finished;
public ThreadedClass(ContainerClass container) {
this.container = container;
thread = new Thread(run);
thread.IsBackground = true;
thread.Start();
}
private void run() {
bool local_finished = false;
while (!local_finished) {
ArrayList to_process = null;
lock (container.list_lock) {
if (container.list.Count > 0) {
to_process = new ArrayList();
to_process.AddRange(container.list);
}
}
if (to_process == null) {
// Nothing to process so wait
lock (this) {
if (!finished) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException) {
}
}
}
} else if (to_process.Count > 0) {
// Something to process, so go ahead and process the journals,
int sz = to_process.Count;
// For all elements
for (int i = 0; i < sz; ++i) {
// Pick the lowest element to process
object obj = to_process[i];
try {
// process the element...
...
} catch (IOException e) {
...
// If there is an error processing the best thing to do is finish
lock (this) {
finished = true;
}
}
}
}
lock (this) {
local_finished = finished;
// Remove the elements that we have just processed.
if (to_process != null) {
lock (container.list_lock) {
int sz = to_process.Count;
for (int i = 0; i < sz; ++i) {
container.list.RemoveAt(0);
}
}
}
// Notify any threads waiting
Monitor.PulseAll(this);
}
}
lock (this) {
actually_finished = true;
Monitor.PulseAll(this);
}
}
public void waitUntilFinished() {
lock (this) {
try {
while (!actually_finished) {
Monitor.Wait(this);
}
} catch (ThreadInterruptedException e) {
throw new ApplicationException("Interrupted: " + e.Message);
}
}
}
public void processList(int until_size) {
lock (this) {
Monitor.PulseAll(this);
int sz;
lock (container.list_lock) {
sz = container.list.Count;
}
// Wait until the sz is smaller than 'until_size'
while (sz > until_size) {
try {
Monitor.Wait(this);
} catch (ThreadInterruptedException ) {
}
lock (container.list_lock) {
sz = container.list.Count;
}
}
}
}
}
}
如您所见,线程一直等到集合为空,但似乎同步冲突禁止线程进入从集合中删除元素的点(整个代码中唯一的一个)@987654322 @在ContainerClass。
如果使用 until_size 的值为 0 调用方法 processList,这种冲突会导致代码永远不会返回,并且应用程序会继续运行。
我请求任何比我更好的开发人员(我想那里有很多)帮助我修复这小段代码,因为我真的不明白为什么列表没有减少......
从心底里非常感谢你。
附言。我想强调代码始终完美工作:唯一会在从ContainerClass.Stop() 调用thread.processList(0) 时停止它的情况。
【问题讨论】:
-
因为我不知道 StackOverflow 中的“社区 wiki”是什么意思,我认为这是一种获得更多可见性的方式......:P
-
您不会因为回答而获得代表积分。查看页面顶部的常见问题解答。
-
在调用 processList(int) 时代码是否也会死锁?或者,就在您通过 0 时?
标签: c# multithreading synchronization