求助winform多线程停止后再开始的方法

gongshunkai3 2013-10-08 02:04:55
需求:多线程停止后点开始按钮能再次开始。

多线程 OnNumberClear();//引发完成事件 threads[i].Abort(); 线程都销毁了,不能重启了,怎么解决?试图不销毁线程,让while退出循环但是失败,请教有何好办法?


private void btnTest_Click(object sender, EventArgs e)
{
Program();
Action();
}
public void test()
{
while (true)
{
if (this.InvokeRequired)
{
Monitor.Enter(this);//锁定,保持同步

.....//代码省略

if (......)
{
OnNumberClear();//引发完成事件
}
}
Monitor.Exit(this);//取消锁定
Thread.Sleep(5);
}
}
private void run()
{
test();
}
public void Program()
{
maxThread = 50;
threads = new Thread[maxThread];
for (int i = 0; i < maxThread; i++)
{
Thread t = new Thread(run);
t.Name = string.Format("{0}", i);
t.IsBackground = true;//程序关闭之后,线程关闭
threads[i] = t;
}
}

public void OnNumberClear()
{
for (int i = 0; i < maxThread; i++)
{
threads[i].Abort();
}
}
public void Action()
{
for (int i = 0; i < maxThread; i++)
{
threads[i].Start();
}
}
...全文
368 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
waleswood 2013-10-09
  • 打赏
  • 举报
回复
引用 12 楼 u010479137 的回复:
放弃了,最后改用BackgroundWorker多线程的方法,感觉这个很好用,比Thread多线程简单许多。 例子:http://www.jb51.net/article/34804.htm
看了大概,使用了ManualResetEvent,希望楼主弄明白ManualResetEvent 和我说的AutoResetEvent的区别,线程同步要小心,很容易出问题。
wangjcltj 2013-10-09
  • 打赏
  • 举报
回复
引用 14 楼 u010479137 的回复:
[quote=引用 13 楼 waleswood 的回复:] [quote=引用 12 楼 u010479137 的回复:] 放弃了,最后改用BackgroundWorker多线程的方法,感觉这个很好用,比Thread多线程简单许多。 例子:http://www.jb51.net/article/34804.htm
看了大概,使用了ManualResetEvent,希望楼主弄明白ManualResetEvent 和我说的AutoResetEvent的区别,线程同步要小心,很容易出问题。[/quote] 至少BackgroundWorker开始、暂停、停止,功能不错的,停止了还能再重新开始,7楼说的重新new一下就能重新开始纯属扯淡,线程Abort()了是不能再恢复的,thread要实现重新开始貌似只能让线程暂停,做出一种停止的假象。反正网上找了很多也没找到用thread很完美的方案。[/quote] 呵呵
Go和分布式IM 2013-10-09
  • 打赏
  • 举报
回复
直接贴代码咯,希望能帮你解决这个问题
System.Threading.AutoResetEvent autoWait = new System.Threading.AutoResetEvent(false);
            bool runFlg = true;
            bool isContinue = true;

            System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(
                (obj) =>
                {
                    autoWait.WaitOne(System.Threading.Timeout.Infinite, false);
                    while (runFlg)
                    {
                        if (!isContinue) break;
                        //To Do Something
                    }
                }));


            //按钮暂停事件中让线程暂停(线程挂起)
            isContinue = false;

            //按钮开始事件中让线程重新开始
            autoWait.Set();
            isContinue = true;

            //销毁线程时
            runFlg = false;
            thread.Abort();
上面只是一个伪代码,楼主实现的时候,需要调整,比如autoWait变成全局变量等。
basibasi 2013-10-09
  • 打赏
  • 举报
回复
用 ManualResetEvent ManualResetEvent .Reset(); ManualResetEvent .WaitOne(); 暂停 ------------------------------------ ManualResetEvent.set(); 继续
gongshunkai3 2013-10-09
  • 打赏
  • 举报
回复
引用 13 楼 waleswood 的回复:
[quote=引用 12 楼 u010479137 的回复:] 放弃了,最后改用BackgroundWorker多线程的方法,感觉这个很好用,比Thread多线程简单许多。 例子:http://www.jb51.net/article/34804.htm
看了大概,使用了ManualResetEvent,希望楼主弄明白ManualResetEvent 和我说的AutoResetEvent的区别,线程同步要小心,很容易出问题。[/quote] 至少BackgroundWorker开始、暂停、停止,功能不错的,停止了还能再重新开始,7楼说的重新new一下就能重新开始纯属扯淡,线程Abort()了是不能再恢复的,thread要实现重新开始貌似只能让线程暂停,做出一种停止的假象。反正网上找了很多也没找到用thread很完美的方案。
gongshunkai3 2013-10-08
  • 打赏
  • 举报
回复
引用 1 楼 wangjcltj 的回复:
挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?
wangjcltj 2013-10-08
  • 打赏
  • 举报
回复
挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
gongshunkai3 2013-10-08
  • 打赏
  • 举报
回复
放弃了,最后改用BackgroundWorker多线程的方法,感觉这个很好用,比Thread多线程简单许多。 例子:http://www.jb51.net/article/34804.htm
waleswood 2013-10-08
  • 打赏
  • 举报
回复
使用 AutoResetEvent的set和WaitOne方法,具体看帮助文档
jiaoshiyao 2013-10-08
  • 打赏
  • 举报
回复
挂起是Suspend 重新启动Start就可以 看你用threads[i]记住要回收啊
wangjcltj 2013-10-08
  • 打赏
  • 举报
回复
引用 8 楼 u010479137 的回复:
[quote=引用 7 楼 wangjcltj 的回复:] [quote=引用 6 楼 u010479137 的回复:] [quote=引用 3 楼 wangjcltj 的回复:] [quote=引用 2 楼 u010479137 的回复:] [quote=引用 1 楼 wangjcltj 的回复:] 挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?[/quote] 就重新Program()一次就重建了,具体可以你还要调整下代码 [/quote] 我都试过了,就重新Program()也没用的,应该怎么调整[/quote] 你的排他锁出问题了。 OnNumberClear();//引发完成事件 这句话把他自己干掉了,后来线程创建成功了,但是无法获取排他锁,所以你感觉没有成功,要在OnNumberClear方法之前先释放排他锁[/quote] 还是不行,排它锁在onNumberClear方法前释放,就会继续执行循环语句(每次循环collectModel.RemoveAt(0);//删除ArrayList中的元素)报错:索引超出范围。必须为非负值并小于集合大小[/quote] 这是你没贴出来的代码问题了,我试了,本来的问题应该是在排他锁上,建议你先把本线程之外的线程全部终止,然后再把排他锁释放,然后将本线程终止
gongshunkai3 2013-10-08
  • 打赏
  • 举报
回复
引用 7 楼 wangjcltj 的回复:
[quote=引用 6 楼 u010479137 的回复:] [quote=引用 3 楼 wangjcltj 的回复:] [quote=引用 2 楼 u010479137 的回复:] [quote=引用 1 楼 wangjcltj 的回复:] 挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?[/quote] 就重新Program()一次就重建了,具体可以你还要调整下代码 [/quote] 我都试过了,就重新Program()也没用的,应该怎么调整[/quote] 你的排他锁出问题了。 OnNumberClear();//引发完成事件 这句话把他自己干掉了,后来线程创建成功了,但是无法获取排他锁,所以你感觉没有成功,要在OnNumberClear方法之前先释放排他锁[/quote] 还是不行,排它锁在onNumberClear方法前释放,就会继续执行循环语句(每次循环collectModel.RemoveAt(0);//删除ArrayList中的元素)报错:索引超出范围。必须为非负值并小于集合大小
wangjcltj 2013-10-08
  • 打赏
  • 举报
回复
引用 6 楼 u010479137 的回复:
[quote=引用 3 楼 wangjcltj 的回复:] [quote=引用 2 楼 u010479137 的回复:] [quote=引用 1 楼 wangjcltj 的回复:] 挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?[/quote] 就重新Program()一次就重建了,具体可以你还要调整下代码 [/quote] 我都试过了,就重新Program()也没用的,应该怎么调整[/quote] 你的排他锁出问题了。 OnNumberClear();//引发完成事件 这句话把他自己干掉了,后来线程创建成功了,但是无法获取排他锁,所以你感觉没有成功,要在OnNumberClear方法之前先释放排他锁
gongshunkai3 2013-10-08
  • 打赏
  • 举报
回复
引用 3 楼 wangjcltj 的回复:
[quote=引用 2 楼 u010479137 的回复:] [quote=引用 1 楼 wangjcltj 的回复:] 挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?[/quote] 就重新Program()一次就重建了,具体可以你还要调整下代码 [/quote] 我都试过了,就重新Program()也没用的,应该怎么调整
chinaheart88 2013-10-08
  • 打赏
  • 举报
回复
现在用并行原理吧
chinaheart88 2013-10-08
  • 打赏
  • 举报
回复
小时候我用过TIMER控件执行再启动。
wangjcltj 2013-10-08
  • 打赏
  • 举报
回复
引用 2 楼 u010479137 的回复:
[quote=引用 1 楼 wangjcltj 的回复:] 挂起用Suspend,你是想挂起,还是重新点击的时候重新开始执行呢?如果要从头执行可以销毁了重建
如何重建?[/quote] 就重新Program()一次就重建了,具体可以你还要调整下代码

110,500

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧