Button_click在windows窗体中

时间:2014-01-01 19:13:12

标签: c# winforms thread-safety

我在下面有这个button5功能。我想要的是当用户想要在按钮5之后点击button1时,button5中的while循环应该中断,因为现在选择是1. Choice是一个全局变量,在开始时设置为零。当button5函数运行时,click1函数在点击时不会被调用。如何解决这个问题?

   This is the Answer Thanks Everyone For the Help!!

         private Thread demoThread = null;
                delegate void SetTextCallback(string text);

     private void button1_Click(object sender, EventArgs e)
            {
                    choice = 1;

                System.Console.WriteLine(choice);
            }     
         private void button5_Click(object sender, EventArgs e)
                    {
                        //button1.Enabled = false;
                        button5.Visible = false;
                        panel2.Visible = true;
                        panel1.Visible = true;
                        panel3.Visible = true;
                        label2.Visible = true;
                        button1.Visible = true;
                        button2.Visible = true;
                        button3.Visible = true;
                        button4.Visible = true;

                        this.demoThread = new Thread(new ThreadStart(this.StartForLoop));

                        this.demoThread.Start();



                    }
                    private void StartForLoop()
                    {
                        while (choice != 1 || choice != 2 || choice != 3)
                        {


                           if (choice == 1 )
                            {
                                choice = 1;
                                break;
                            }

                           if (choice == 2)
                           {
                               choice = 2;
                               break;
                           }

                           if (choice == 3)
                           {
                               choice = 3;
                               break;
                           }
                            Application.DoEvents();

                        }
                        System.Console.WriteLine("AAA");
                        if (choice == 3)//why
                        {
                        }
                        if (choice == 1)//true
                        {
                            System.Console.WriteLine("label");

                            this.SetText("Does the animal lay eggs?");
                        }
                        if (choice == 2)//false
                        {
                        }

                    }

3 个答案:

答案 0 :(得分:3)

这是一个错误的概念。永远不要使用Application.DoEvents();,这是一个黑客攻击。它没有解决你的任何问题。

你在Button5_Click中不需要while循环。该循环中的所有内容都可以通过其他单击处理程序中的代码来处理。

您的问题可能由state machine解决。这看起来很复杂,但它不是。尝试尽可能简单地实现它,并在遇到问题时提出另一个问题。

答案 1 :(得分:1)

你遇到Thread的问题,问题是你编程Thread忙于你的button5循环,直到它完成处理button5代码,你的线程将不会注意更多的东西。

要解决此问题,您必须在新线程中运行while循环,如下所示:

Thread t = new Thread (new ThreadStart(delegate(){
    //while goes here along with the if's...
}));
t.Start();

在button1中,更改全局变量的值时 现在可以知道在button5中启动的线程内部的代码 你的改变和行为相应。

另外要注意以下事项,因为选择是一个全局变量 它现在可以通过两个线程同时访问程序线程 和你的新线程,因为这确保你访问选择变量 使用互斥锁,在c#中,您可以访问线程共享变量,如下所示:

//declare this next to your choice variable.
Object mux_choice = new Object();

lock(mux_choice){
   //changing choice here is thread safe.
}

由于选择似乎是值类型,因此您必须创建一个对象来表示对值类型变量(http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx)的访问。

您在C#中有更多关于线程的信息: http://www.albahari.com/threading/

注意:确保在使用它的任何地方保护选择变量。

另外,根据您的评论,我假设您要修改表单控件 属性,如label2.Text =“...”因此,如果你这样做,你将面临交叉线程异常。要修改Controls属性,必须调用Invoke方法,该方法调用UI线程中的更改,如下所示:

label2.Invoke((MethodInvoker)(() => label2.Text = "some text"));

根据.NET框架版本,这里是与.NET 2.0兼容的代码:

label2.Invoke(new MethodInvoker(delegate(){ label2.Text = "some text"; }));

问候。

答案 2 :(得分:1)

最好的方法是为每个循环运行一个到另一个线程,这样就不会打扰表单的UI。 用户可以轻松点击按钮1。

只是为了基本的想法:

 private void button5_Click(object sender, EventArgs e)
   {
    button5.Visible = false;
    panel2.Visible = true;
    panel1.Visible = true;
    panel3.Visible = true;
    label2.Visible = true;
    button1.Visible = true;
    button2.Visible = true;
    button3.Visible = true;
    button4.Visible = true;
    Thread thread = new Thread(new ThreadStart(StartForLoop));
    thread.Start();    
    }


 public void StartForLoop()
    {
      while (choice != 1 || choice != 2 || choice != 3)
     {
       if (choice == 1 || choice == 2 || choice == 3)
        {
          choice = 1000;
          break;
        }
       Application.DoEvents();
     }

    if(choice==3)//why
    {
    }
    if(choice==1)//true
    {
    label2.Text = "asdasd";
    }
    if(choice==2)//false
    {
    }
   }

PS:更好地实现锁定选择