C#窗体:一个可以控制UI的线程;睡眠;而不暂停整个程序.怎样

本文关键字:睡眠 怎样 线程 暂停 程序 控制 窗体 一个 UI | 更新日期: 2023-09-27 18:06:40

好。。。

看起来同一程序中的WinForms和Threading是我无法轻松掌握的东西。

我正在尝试用两个图片框(使用按钮(和一个文本框制作一个自定义的数字上下。是的,我可以使用默认的NumericUpDown表单,但我想制作一个外观不同的表单。

我试过用定时器(System.Windows.Forms.Timer(来做这件事。问题是,当一个定时器遇到"Thread.Sleep(int("时,整个程序就会"进入睡眠状态"。

我试着用线。某些类型的线程无法控制UI。然后我尝试了这个

private void declare_thread()
{
    //some work
    Thread delay = new Thread(new ThreadStart(delay0));
    delay.Start();
    //some more work
}
//other functions
private void delay0()
{
    //delay_for_500ms.WaitOne();
    this.Invoke((ThreadStart)delegate()
    {
    Thread.Sleep(500);
    if (is_mouse_down)
    timer1.Enabled = true;
    });
}

结果和我只使用计时器时一样。

所以,我想自定义数字上下。但我做不好。我知道我做错了。我想制作一个线程,它可以控制UI,并且在调用"thread.Sleep(int("时不会使整个程序暂停。

请给我初学者的答案。到目前为止,我还没有找到一个好的答案来告诉我正确的方法,而且很容易理解。

C#窗体:一个可以控制UI的线程;睡眠;而不暂停整个程序.怎样

您正在寻找问题的错误答案。没有线程可以访问UI控件睡眠而不阻塞UI。只有UI线程可以安全地访问UI控件,如果您使UI线程处于睡眠状态,则UI将无响应。

恐怕你需要咬紧牙关,学会如何正确地穿线。请注意,睡眠几乎总是错误的方法,尤其是在UI线程中。你甚至没有真正说出你想做什么,但计时器是一种很好的表达方式,"我想在稍后的时间点执行一些操作。".NET中有各种不同的计时器-你应该使用哪一个取决于你想做的事情。

线程是一个你无法真正快捷的主题——你应该考虑阅读一本完整的教程或一本详细介绍它的书。

要回答您的实际问题,请使用以下命令:

private void declare_thread()
{
    //some work
    Thread delay = new Thread(new ThreadStart(delay0));
    delay.Start();
    //some more work
}
//other functions
private void delay0()
{
    //delay_for_500ms.WaitOne();
    Thread.Sleep(500);
    this.Invoke((ThreadStart)delegate()
    {
    if (is_mouse_down)
    timer1.Enabled = true;
    });
}

当然,你正确的事件驱动程序编程的整个心理模型是错误的。你会更好地适应20年前DOS的老员工。

如果您想等待半秒再做某事,请将计时器设置为500ms,然后退出您的功能。让计时器告诉你什么时候完成,这样你就可以完成下半场:

// on the main thread
// la la la doing work
// wait 500ms
var tmr=new Timer{Interval=500};
tmr.Tick+=(s,e)=>{/*action .5sec later*/ btn.Enabled=false; tmr.Enabled=false;};
tmr.Enabled=true;
// and quit
return;

如果您愿意下载Async CTP(或等待C#5.0(,您可以使用新的asyncawait关键字来创建一个真正优雅的解决方案1

public class YourForm : Form
{
  private async void UpPictureBox_Click(object sender, EventArgs args)
  {
    await Task.Delay(500);
    timer1.Enabled = is_mouse_down;
  }
  private async void DownPictureBox_Click(object sender, EventArgs args)
  {
    await Task.Delay(500);
    timer1.Enabled = is_mouse_down;
  }
}

上面代码中的await关键字将在执行延迟任务时将控制权交回消息循环。执行将在完成该任务后重新开始。这只是新关键词如此酷的众多原因之一。


1请注意,异步CTP使用TaskEx而不是Task

button.Click += delegate { BeginInvoke(new UiUpdate(delegate { Thread.Sleep(500); // Do Stuff After Sleep };)) };
private delegate void UiUpdate();