C#Winforms:一个可以控制UI并且可以“休眠”而不会暂停整个程序的线程。怎么样?

时间:2011-08-26 14:50:52

标签: c# winforms multithreading

行...

在同一个程序中看起来像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)”时不会使整个程序暂停。

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

4 个答案:

答案 0 :(得分:8)

你正在寻找问题的错误答案。在没有阻止UI的情况下,没有可以访问UI控件睡眠的线程。只有UI线程可以安全地访问UI控件,如果你让UI线程休眠,你的UI将没有响应。

我担心你需要咬紧牙关并学习如何正确执行线程。请注意,睡眠几乎总是错误的方法 - 尤其是在UI线程中。你还没有真正说出你想要做的事情,但计时器是一种很好的方式,“我想在以后的某个时间点执行一些动作。”有various different timers in .NET - 你应该使用哪一个取决于你想要做什么。

线程是你无法真正快捷的主题之一 - 你应该考虑阅读thorough tutorial或一本详细介绍它的书。

答案 1 :(得分:1)

要回答您的实际问题,请使用:

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人员。

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

// 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;

答案 2 :(得分:0)

如果您愿意下载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

答案 3 :(得分:-1)

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

private delegate void UiUpdate();