Form1 : Form
    {
        private delegate void Method();    //委托申明,子线程条用UI中的方法
        private ArrayList Config = new ArrayList();//模拟装所有端口配置
        private ArrayList done = new ArrayList();//装完成端口
        private long AlivedThread = 0;//当前存活线程数
        public Form1()
        {
            InitializeComponent();
        }

        
private void button1_Click(object sender, EventArgs e)
        {
            done.Clear();
//将完成项清空
            toolStripProgressBar1.Value = 0;//设置初始值
            Random rand = new Random(200); //下面和循环,模拟初始化端口配置项
            int max=rand.Next(1000);
            
for (int i = 0; i < max; i++)
            {
                Config.Add(rand.Next());
            }
            toolStripProgressBar1.Minimum 
= 0;
            toolStripProgressBar1.Maximum 
= Config.Count;

            
foreach (object item in Config)//循环扫描每项
            {
        again: 
if (Interlocked.Read(ref AlivedThread) < 10)
                {
                    Thread ScanThread
= new Thread

                   (
new ParameterizedThreadStart(ScanFunc));
                    ScanThread.Start(item);
                    Thread.Sleep(
10);
                }
                
else
                {
                    Thread.Sleep(
10);
                    
goto again;
                }
            }

                        
        }

       
private void ScanFunc(object item)
        {
            Interlocked.Increment(
ref AlivedThread);
            Monitor.Enter(done);
            done.Add(item);
            Monitor.Exit(done);
            Thread.Sleep(
500);
            SetProgressMethod();
            Interlocked.Decrement(
ref AlivedThread);
        }

        
private void SetProgressMethod()
        {
            MethodInvoker mi 
= new MethodInvoker(this.SetProgressBar);
            
this.BeginInvoke(mi);
            Thread.Sleep(
100);
        }

        
private void SetProgressBar()
        {
            Monitor.Enter(done);
            toolStripProgressBar1.Value 
= done.Count;
            Monitor.Exit(done);
            
this.Refresh();
        }

就上面代码老是出现主窗体死亡,对用户操作没有任何反应的情况。我在网上四处找,一好心网友也给了我相关代码,但和我的类似,实例只有两个线程,一个线程主线程,一个控制进度条。今天看了CSDN上愈翁的一篇文章,内容同样很简单,也好似两个线程,和我得到的代码类似。但是我看到文章下面有网友提问,作者有一句关键的回答,“线程提交给UI处理A任务,而UI正在处理B任务”,我这才回过神来。原来我的主线程中有个foreach循环,UI线程一直处理它呢,没有时间相应子线程提交任务!

   于是马上对代码做了修改:新建一线程函数,将循环放到该线程中执行,修改如下:

       
private void LoopFun()

      {

          
foreach (object item in Config)//循环扫描每项
            {
        again: 
if (Interlocked.Read(ref AlivedThread) < 10)
                {
                    Thread ScanThread
= new Thread

                   (
new ParameterizedThreadStart(ScanFunc));
                    ScanThread.Start(item);
                    Thread.Sleep(
10);
                }
                
else
                {
                    Thread.Sleep(
10);
                    
goto again;
                }
            }



       }

然后在主线程中申明另一线程执行该函数,

Thread loop 
= new Thread(new ThreadStart(LoopFun));
            loop.Start();

测试,程序工作时,UI完全能正常反应用户操作了!

最后,在做多线程程序时,一定要遵循费时操作不放在主线程中的原则!

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2018-02-08
  • 2022-12-23
  • 2021-11-28
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-07-08
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-02-27
  • 2022-12-23
  • 2021-10-12
相关资源
相似解决方案