C#启动和停止同一按钮点击事件内的线程

C#启动和停止同一按钮点击事件内的线程,c#,multithreading,winforms,visual-studio-2010,.net-4.0,C#,Multithreading,Winforms,Visual Studio 2010,.net 4.0,我正在使用C#、.Net4.0和Visual Studio 2010,当用户单击按钮时,我试图从我的windows窗体应用程序中获得此行为: GUI LED开始闪烁 长横档操作开始 当点2的操作结束时,LED停止闪烁 private void Btn_WebService_Click(object sender, EventArgs e) { Thread_Blink = new Thread(() => { LED_Blink(LED.WS); }); Thread_Bl

我正在使用C#、.Net4.0和Visual Studio 2010,当用户单击按钮时,我试图从我的windows窗体应用程序中获得此行为:

  • GUI LED开始闪烁
  • 长横档操作开始
  • 当点2的操作结束时,LED停止闪烁

    private void Btn_WebService_Click(object sender, EventArgs e)
    {
        Thread_Blink = new Thread(() => { LED_Blink(LED.WS); });
        Thread_Blink.Start();
    
        // Do something that takes time.. Let's imulate with a sleep
        Thread.Sleep(2000);
    
        Thread_Blink.Abort();
    }
    
  • 我还尝试使用3种不同的事件和/或计时器

    private void Btn_WebService_MouseDown(object sender, MouseEventArgs e)
    {
       Timer_Blink.Enabled = true;
    }
    
    private void Btn_WebService_Click(object sender, EventArgs e)
    {
        // Do something that takes time.. Let's imulate with a sleep
        Thread.Sleep(2000);
    }
    
    private void Btn_WebService_MouseUp(object sender, MouseEventArgs e)
    {
        Timer_Blink.Enabled = false;
    }
    
    结果总是一样的:只有在长时间运行的操作结束时(
    Thread.Sleep(2000);
    )LED才会开始闪烁,然后突然停止,使您看不到任何东西。为什么会发生这种情况?我如何才能获得期望的行为

    我添加了更多信息。我尝试使用BackgroundWorked并以这种方式实现了想要的行为:

    private void Btn_WebService_Click(object sender, EventArgs e)
        {
            BlinkWorker.RunWorkerAsync(LED.WS);
            LedOn(LED.WS);
    
            TestWebService();   // This method takes about 2 seconds to answer..
    
            LedOff(LED.WS);
            BlinkWorker.CancelAsync();
        }
    
    当TestWebService()运行时,我会关闭指示灯(LedOn(LED.WS);)。TestWebService()完成后,指示灯亮起。 如果在Click事件中启动并取消,BlinkWorker仍不工作


    仅供参考:如果我制作了一个启动闪烁的按钮和另一个停止闪烁的按钮,那么效果会很好。

    我建议您查看一下BackgroundWorker类和ReportProgress方法。

    问题是,您将UI线程捆绑在
    线程中。Sleep
    。UI线程是特殊的-它是唯一可以更改UI的线程-因此,当它忙于睡眠时,它无法为
    BackgroundWorker
    LED闪烁
    计时器回调更改UI状态的任何尝试提供服务

    因此,您不需要占用UI线程。您需要将
    线程.Sleep
    代码(或其实际等效代码)放入
    BackgroundWorker
    s
    DoWork
    处理程序,或使用其他方法避免阻塞UI线程

    如果您尝试执行的实际工作已经提供了异步替代方案(例如,
    wait Task.Delay(2000);
    相当于您当前的
    线程。Sleep(2000);
    ),则当前常用的方法是使用
    async
    /
    wait
    )。不幸的是,使用
    async
    await
    将需要您迁移到.NET/Visual Studio的更高版本,但无论如何您都应该考虑这一点。2010年已经过时了(而且,IMO可能是最糟糕的一年——它的速度非常慢),而.NET 4.0(相对于.NET 4.5.2或更高版本)不再受支持