窗体中放置一个标签,formload中开启一个线程使得标签移动,使用了委托。运行时,主线程失去响应,整个进程占用了很多CPU,窗体的别的操作都不响应

解决方案 »

  1.   

    这种做法听起来就不妥。如果CPU占用很高,就是有类似循环操作在运行,比如A操作触发B操作,B操作又触发A操作。如果要移动一个Label,应该在主线程中做比较好,就算需要另一个线程驱动,也不应该再子线程中去操作主线程的Label,比较雅致的做法是发消息到主线程,主线程接受到消息后完成对应的控件操作。
      

  2.   

    窗体上不同位置放置两个标签label1和label2,使用Timer就可以实现滚动Public Class Form1    Dim WithEvents T1 As Timer
        Dim WithEvents T2 As Timer    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            If T1 IsNot Nothing Then
                T1.Stop()
                T1.Dispose()
            End If        If T2 IsNot Nothing Then
                T2.Stop()
                T2.Dispose()
            End If
        End Sub    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            T1 = New Timer
            T1.Interval = 200
            T1.Start()        T2 = New Timer
            T2.Interval = 200
            T2.Start()
        End Sub    Private Sub T1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles T1.Tick
            If Label1.Left + Label1.Width > Me.Width Then
                Label1.Left = 0
            Else
                Label1.Left += 10
            End If
        End Sub    Private Sub T2_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles T2.Tick
            If Label2.Left > 0 Then
                Label2.Left -= 10
            Else
                Label2.Left = Me.Width
            End If
        End SubEnd Class
      

  3.   

    我想知道为什么主线程会失去响应,标签移动的方法里用了while(true){}循环while (true)
    {
      if (lblMsg.Left >= this.Width)
      {
        lblMsg.Left = 0;
      }
      lblMsg.Left += 1;
      Thread.Sleep(100);
    }
      

  4.   

    不能在子线程操作主线程的控件!要操作也应该使用Invoke
      

  5.   

    这是方法里的所有内容
    private void MoveMsg()
    {
    startMove start = delegate()
                {
                    if (lblMsg.InvokeRequired)
                    {
                        lblMsg.Invoke(new MethodInvoker(MoveMsg));
                    }
                    else
                    {
                        while (true)
                        {
                            if (lblMsg.Left >= this.Width)
                            {
                                lblMsg.Left = 0;
                            }
                            lblMsg.Left += 1;
                            Thread.Sleep(100);
                        }
                    }
                };
                lblMsg.Invoke(start);
      

  6.   

    用一个Lock(this)这个方法.加以控制.
    或则用.waitone这个方法.
      

  7.   

    试过了,主线程还是没有响应,我把while循环改为运行有限次,运行结束后,主线程得到响应,不知道为什么?
      

  8.   

    刚才我把方法改成这样就可以了
    private void MoveMsg()
    {
        startMove start = delegate()
        {
             if (lblMsg.InvokeRequired)
             {
                   lblMsg.Invoke(new MethodInvoker(MoveMsg));
             }
             else
             {
                   if (lblMsg.Left >= this.Width)
                   {
                        lblMsg.Left = 0;
                    }
                    lblMsg.Left += 1;
                    Thread.Sleep(100);
                    }
              }
          };
          while(true)
          {
          lblMsg.Invoke(start);
          }

      

  9.   

    我在vb中试了试,下面这段代码完全可以分别控制两个标签在窗体上向不同的方向循环运动,同时窗体仍相应其它事件。不妨看一下吧。Public Class Form1    Dim t1, t2 As Threading.Thread    Private Delegate Sub Run1(ByVal Reset As Boolean)
        Private Delegate Sub Run2(ByVal Reset As Boolean)    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            t1.Abort()
            t2.Abort()
        End Sub    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            t1 = New Threading.Thread(AddressOf Sub1) : t1.Start()
            t2 = New Threading.Thread(AddressOf Sub2) : t2.Start()
        End Sub    Private Sub Move1(ByVal Reset As Boolean)
            If Reset Then Label1.Left = 0 Else Label1.Left += 1
        End Sub    Private Sub Move2(ByVal Reset As Boolean)
            If Reset Then Label2.Left = Me.Width Else Label2.Left -= 1
        End Sub    Private Sub Sub1()
            Do
                If Label1.Left < Me.Width Then
                    Me.Invoke(New Run1(AddressOf Move1), False)
                Else
                    Me.Invoke(New Run1(AddressOf Move1), True)
                End If
                Threading.Thread.Sleep(10)
            Loop
        End Sub    Private Sub Sub2()
            Do
                If Label2.Left > 0 Then
                    Me.Invoke(New Run2(AddressOf Move2), False)
                Else
                    Me.Invoke(New Run2(AddressOf Move2), True)
                End If
                Threading.Thread.Sleep(10)
            Loop
        End SubEnd Class
      

  10.   

    在c#中实现了楼上的代码,只是没有用带参的,而在move方法中判断标签是否超过了边界,执行的时候主线程依然没有响应。且标签移出边界后就不再出现了。
    但是调试代码的时候发现标签的left值变化是正确的,执行时移出边界后却不出现了
    头疼中……
      

  11.   

    To B_cat:
    照你的意思是不是这样,在move方法中判断标签是否超过了边界Public Class Form1    Dim t1, t2 As Threading.Thread    Private Delegate Sub Run1()
        Private Delegate Sub Run2()
        Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
            t1.Abort()
            t2.Abort()
        End Sub    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            t1 = New Threading.Thread(AddressOf Sub1) : t1.Start()
            t2 = New Threading.Thread(AddressOf Sub2) : t2.Start()
        End Sub    Private Sub Move1()
            If Label1.Left < Me.Width Then
                Label1.Left += 1
            Else
                Label1.Left = 0
            End If
        End Sub    Private Sub Move2()
            If Label2.Left > 0 Then
                Label2.Left -= 1
            Else
                Label2.Left = Me.Width
            End If
        End Sub    Private Sub Sub1()
            Do
                Me.Invoke(New Run1(AddressOf Move1))
                Threading.Thread.Sleep(10)
            Loop
        End Sub    Private Sub Sub2()
            Do
                Me.Invoke(New Run2(AddressOf Move2))
                Threading.Thread.Sleep(10)
            Loop
        End Sub
      
    End Class我试了试,在vb中依然没有问题。可以拖动窗体,可以点击按钮。
      

  12.   

    public partial class Form1 : Form
        {
            public delegate void run1();
            public delegate void run2();        Thread threadCn;
            Thread threadEn;
            public Form1()
            {
                InitializeComponent();
            }
         
            private void Form1_Load(object sender, EventArgs e)
            {        }        private void moveCn()
            {
                
                while (true)
                {
                    this.Invoke(new run1(startCn));
                }
            }        private void startCn()
            {
                //while (true)
                //{
                    if (lblCn.Left >= this.Width)
                    {
                        lblCn.Left = 0;
                    }
                    lblCn.Left += 50;
                    Thread.Sleep(50);
                //}
            }        private void moveEn()
            {
                
                while (true)
                {
                    this.Invoke(new run2(startEn));
                }
            }        private void startEn()
            {
                //while (true)
                //{
                if (lblEn.Left <= -lblEn.Width)
                {
                    lblEn.Left = this.Width;
                }
                lblEn.Left -= 50;
                Thread.Sleep(50);
                //}
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                threadCn.Abort();
                threadEn.Abort();
            }        private void button1_Click(object sender, EventArgs e)
            {
                threadCn = new Thread(new ThreadStart(moveCn));
                threadCn.Start();
                threadEn = new Thread(new ThreadStart(moveEn));
                
                threadEn.Start();
            }
        }
      

  13.   

    楼上方法可行。lz的问题没有必要用委托,委托一般用于异步回调和线程间调用控件,lz的问题用上面的线程就可以解决。
      

  14.   

    知道了,两句Thread.Sleep(50)放的位置不对。呵呵。
    我给你放到while循环里了。using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;namespace WindowsApplication2
    {
        public partial class Form1 : Form
        {
            public delegate void run1();
            public delegate void run2();        Thread threadCn;
            Thread threadEn;
            public Form1()
            {
                InitializeComponent();
            }        private void Form1_Load(object sender, EventArgs e)
            {        }        private void moveCn()
            {            while (true)
                {
                    this.Invoke(new run1(startCn));
                    Thread.Sleep(50);
                }
            }        private void startCn()
            {
                //while (true)
                //{
                if (lblCn.Left >= this.Width)
                {
                    lblCn.Left = 0;
                }
                lblCn.Left += 50;
               
                //}
            }        private void moveEn()
            {            while (true)
                {
                    this.Invoke(new run2(startEn));
                    Thread.Sleep(50);
                }
            }        private void startEn()
            {
                //while (true)
                //{
                if (lblEn.Left <= -lblEn.Width)
                {
                    lblEn.Left = this.Width;
                }
                lblEn.Left -= 50;
                
                //}
            }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                threadCn.Abort();
                threadEn.Abort();
            }        private void button1_Click(object sender, EventArgs e)
            {
                threadCn = new Thread(new ThreadStart(moveCn));
                threadCn.Start();
                threadEn = new Thread(new ThreadStart(moveEn));            threadEn.Start();
            }
        }
    }