C# 根据其他按钮激活或停用按钮

C# 根据其他按钮激活或停用按钮,c#,.net,winforms,button,C#,.net,Winforms,Button,我是新来的。我有两个按钮和两个标签。我想要的是,当我单击按钮1时,它开始计数并显示在标签1中。当我按下按钮2时,它会在按钮1下继续计数,并在按钮2下开始计数,并显示在标签2中。这是我的密码 bool testt = true; int i = 0; int j = 0; private void button1_Click(object sender, EventArgs e) { while (testt) { label1.Text = i.ToString

我是新来的。我有两个
按钮
和两个
标签
。我想要的是,当我单击
按钮1
时,它开始计数并显示在
标签1
中。当我按下
按钮2
时,它会在
按钮1
下继续计数,并在
按钮2
下开始计数,并显示在标签2中。这是我的密码

bool testt = true;
int i = 0;
int j = 0;

private void button1_Click(object sender, EventArgs e)
{
    while (testt)
    {
        label1.Text = i.ToString();
        i++;
        System.Threading.Thread.Sleep(50);
        if (i > 5000)
        {
            i = 0;
        }
    }
}

private void button2_Click(object sender, EventArgs e)
{
    testt = false;
    while (!testt)
    {
        label2.Text = j.ToString();
        j++;
        System.Threading.Thread.Sleep(50);
        if (j > 5000)
        {
            i = 0;
        }
    }
}

这里的问题是当我点击一个按钮时,它不允许我点击另一个按钮。我使用了一个全局变量来检测按下了哪个按钮。但它不起作用。我怎样才能做到这一点

这里的问题是线程问题

当您使用winforms时,主线程的任务是显示和使界面交互,并执行您赋予它的任何任务

在代码中,开始倒计时。但是在那里,使界面工作的同一个线程现在正忙于降低您的值,因此它在准备就绪之前不会更新界面或响应按钮

您需要的是一个助手线程来为您进行倒计时(或者老实说,启动一个计时器)。否则,在完成该循环之前,界面将是非交互式的

定时器是最简单的方法


您在UI线程上执行所有这些操作,因此您正在阻止它。您需要让另一个线程执行实际计数,并使用
控件将标签更改委托给主线程。调用
,以便主线程有时间运行消息泵。您可以使用内置的
BackgroundWorker
,或者使用
ThreadPool
TaskFactory
创建线程

我已经写了一个简短的例子,说明了如何使用LINQ和ThreadPool实现这一点,这不是设计方面的最佳方法,但它将为您提供一个开发适当解决方案的起点

    semaphore = true;
    int i = 0;
    int j = 0;

    private void button1_Click(object sender, EventArgs e)
    {
        semaphore = true;
        ExecuteAsync(()=>
            {
                while (semaphore)
                {
                    //Dispatch a call to the UI thread to change the label
                    Invoke((MethodInvoker)(() => ChangeLabel(label1, i.ToString())));
                    i++;
                    Thread.Sleep(50);
                    if (i > 5000)
                    {
                        i = 0;
                    }
                }
            });
    }

    //Executes a function on a ThreadPool thread
    private void ExecuteAsync(Action action)
    {
        ThreadPool.QueueUserWorkItem(
            obj => action());
    }

    private void ChangeLabel(Label label, string labelText)
    {
        label.Text = labelText;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        semaphore = false;
        ExecuteAsync(() =>
                {
                    while (!semaphore)
                    {
                        //Dispatch a call to the UI thread to change the label
                        Invoke((MethodInvoker)(() => ChangeLabel(label2, j.ToString())));
                        j++;
                        Thread.Sleep(50);
                        if (j > 5000)
                        {
                            i = 0;
                        }
                    }
                });
    }

实际上这是另一个问题的总结。我只是在这里提出了这个概念。我需要知道如何在没有计时器的情况下完成这项工作。在这种情况下,您需要生成一个新线程,比如BackgroundWorker类。问题是,然后您需要委派单击任务,因为ui只能在主线程上完成。快速、简单且非常脏的修复方法是在循环中运行Application.DoEvents()。这可能会有所帮助:我尝试使用BackgroundWorker。在这种情况下,计数显示在标签中,但我仍然无法单击另一个按钮,当我单击按钮1时,它工作,当我单击按钮2时,它继续按钮1计数,并在按钮2下开始计数,但当我再次单击按钮1时,它不再工作,标签2继续计数。无论如何,谢谢你的解决方案非常感谢。你能给我一个ExecuteAsync方法教程的链接吗?ExecuteAsync方法是我们定义的,它利用了线程池。此链接应为您提供有关线程池使用的基本信息。祝你好运。再次感谢你的帮助。跟着这个走