private int flag = 0;
Thread[] threads = new Thread[20];
private object LockThis = new System.Object();
private void button4_Click(object sender, EventArgs e)
{
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(threadMethod));
threads[i].Start(i);
}
}
private void threadMethod(object n)
{
for (int i = 0; i < 100; i++)
{
lock (LockThis)
{
flag++;
Console.WriteLine( flag.ToString());
if (flag >= 300)
{
Console.WriteLine("线程"+n.ToString()+"检测到flag已经达到目标数值,自动终结所有线程");
foreach (Thread t in threads)
{
t.Abort();
}
}
}
}
}
实际运行的时候,是这样的,总有几个线程没有被结束掉:
。。。。。。
295
296
297
298
299
300
线程2已经达到目标数值,自动终结所有线程
301
线程3已经达到目标数值,自动终结所有线程
302
线程8已经达到目标数值,自动终结所有线程
上面的代码出问题在什么地方呢?除了上面的用Lock,还有什么更好的方法呢?
6 个解决方案
#1
线程最好让它自行了断, 都去判断 flag 就可以了.
#2
终结的过程中有新线程启动,就是说终结300的时间片间隙启动了新线程咯
#3
1、明明只操作同一个变量,你却让每个线程都对它进行同样的监视和处理,而对所有线程的Abort()又几乎是同时发生的,这一瞬间每个人都在杀掉所有人,这是一个很不周全的逻辑,可以想象你的程序当flag为300时已经混乱成什么样子,很可怕
2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。
3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。
2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。
3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。
#4
看到滥用线程的人我们会“绕着走”,因为一个团队开发的产品不能因为有人任性而垮掉(死掉)。
如果你确实需要修改一个变量,那么修改变量之前判断一下
if(abc<=300)不就完了嘛。儿你满脑子的都是光怪陆离的程序幻象,没有灭定的习惯。
{
.....修改它
}
#5
假设就算是“玩儿”线程,在你的 for 循环中,在 flag++ 语句之前,写
很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。
纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?
if (flag > 300)
return;
很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。
纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?
#6
判断写在线程方法内
另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。
另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。
#1
线程最好让它自行了断, 都去判断 flag 就可以了.
#2
终结的过程中有新线程启动,就是说终结300的时间片间隙启动了新线程咯
#3
1、明明只操作同一个变量,你却让每个线程都对它进行同样的监视和处理,而对所有线程的Abort()又几乎是同时发生的,这一瞬间每个人都在杀掉所有人,这是一个很不周全的逻辑,可以想象你的程序当flag为300时已经混乱成什么样子,很可怕
2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。
3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。
2、原则上不应在线程外结束它,这样会在线程内引发“正在终止线程”的异常,而你又没有对这些异常进行处理,所以会导致程序不会按照“看上去应该这样跑”的流程运行,举个例子:当有一个线程已经杀掉两个线程的时候,突然被别人给Abort了,这时就发生了异常,剩下的线程是不是就无法进行处理了?而同样的事情发生在每个线程中,我想这应该是关键所在。
3、你在Abort()时应当先判断这个线程对象是否IsAlive,这里同样可能引发异常。多线程本来就不安全,而你通篇没有一个异常处理,这样非常不负责任。
#4
看到滥用线程的人我们会“绕着走”,因为一个团队开发的产品不能因为有人任性而垮掉(死掉)。
如果你确实需要修改一个变量,那么修改变量之前判断一下
if(abc<=300)不就完了嘛。儿你满脑子的都是光怪陆离的程序幻象,没有灭定的习惯。
{
.....修改它
}
#5
假设就算是“玩儿”线程,在你的 for 循环中,在 flag++ 语句之前,写
很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。
纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?
if (flag > 300)
return;
很简单的流程,这就完毕了,这是基本流程,不管有多少线程你都得写这个flag<300或者flag>300的判断才算是附和最基本的业务逻辑判断。
纠结 Abort 是多余的。连业务逻辑都没有写对,怎么可能写纯技术的代码呢?
#6
判断写在线程方法内
另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。
另外详细阅读MSDN上关于Abort的解释,可以解决你的疑惑。