开发者

C# Winforms: A thread that can control the UI and can "sleep" without pausing the whole program. How?

OK...

Looks like WinForms and Threading in the same program is something that I can't master easily.

I'm trying to make a custom Numeric Up Down out of two picture boxes (used a buttons) and a text box. Yes, I can use the default NumericUpDown form, but I开发者_JAVA技巧 want to make a different looking one.

I have tried to do that with timers (System.Windows.Forms.Timer). The problem is that when one timer meets "Thread.Sleep(int)", the whole program "falls to sleep".

I tried with threads. Some types of threads can't control the UI. Then I tried this

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;
    });
}

The result was the same as when I used timers only.

So, I want to make custom Numeric Up Down. But I can't get it right. I know I'm doin' it wrong. I want to make a thread that can control the UI and doesn't make the whole program pause when calling "Thread.Sleep(int)".

Please, give me answers for beginners. So far I haven't found a good answer that can show me the right way and it's easy to understand.


You're looking for the wrong answer to the problem. There's no such thing as a thread which can access UI controls and sleep without blocking the UI. Only the UI thread can access UI controls safely, and if you make the UI thread sleep, your UI will be unresponsive.

I'm afraid you need to bite the bullet and learn how to perform the threading properly. Note that sleeping is almost always the wrong approach - especially in the UI thread. You ahven't really said what you're trying to do, but a timer is a good way of saying, "I want to perform some action at a later point in time." There are various different timers in .NET - which one you should use will depend on what you're trying to do.

Threading is one of those topics that you can't really shortcut - you should consider reading a thorough tutorial or a book which covers it in detail.


To answer your actual question, use this:

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;
    });
}

Of course your whole mental model of proper, event driver programming is wrong. You'd fit in better with the old single-task DOS people 20 years ago.

If you want to wait half a second before doing something, set a timer for 500ms and exit your function. Let the timer tell you when it's done so you can do the second half:

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


If you are willing to download the Async CTP (or wait for C# 5.0) you can use the new async and await keywords to make for a really elegant solution.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;
  }
}

The await keyword in the code above will yield control back to the message loop while the delay task is executing. Execution will pick back up where it left off upon completion of that task. This is but one among many reasons why the new keywords are so wicked cool.


1Note that the Async CTP uses TaskEx instead of Task.


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

private delegate void UiUpdate();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜