[英]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. 在同一个程序中看起来像WinForms和Threading是我无法轻易掌握的东西。
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 want to make a different looking one.
是的,我可以使用默认的NumericUpDown表单,但我想做一个不同的表单。
I have tried to do that with timers (System.Windows.Forms.Timer). 我试图用计时器(System.Windows.Forms.Timer)来做到这一点。 The problem is that when one timer meets "Thread.Sleep(int)", the whole program "falls to sleep".
问题是当一个计时器遇到“Thread.Sleep(int)”时,整个程序“陷入睡眠”。
I tried with threads. 我试过线程。 Some types of threads can't control the UI.
某些类型的线程无法控制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)".
我想创建一个可以控制UI的线程,并且在调用“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.
没有一个线程可以访问UI控件和睡眠而不会阻止UI。 Only the UI thread can access UI controls safely, and if you make the UI thread sleep, your UI will be unresponsive.
只有UI线程可以安全地访问UI控件,如果您使UI线程处于休眠状态,您的UI将无法响应。
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.
请注意,睡眠几乎总是错误的方法 - 尤其是在UI线程中。 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.
.NET中有各种不同的计时器 - 你应该使用哪一个取决于你想要做什么。
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.
20年前,你可以更好地适应旧的单任务DOS人员。
If you want to wait half a second before doing something, set a timer for 500ms and exit your function. 如果您想在做某事之前等待半秒钟,请将计时器设置为500毫秒并退出您的功能。 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. 如果您愿意下载Async CTP (或等待C#5.0),您可以使用新的
async
和await
关键字来制作一个非常优雅的解决方案。 1 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. 上面的代码中的
await
关键字将在延迟任务执行时将控制权返回给消息循环。 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.
这只是新关键词如此邪恶酷炫的众多原因之一。
1 Note that the Async CTP uses TaskEx
instead of Task
. 1 请注意,Async CTP使用
TaskEx
而不是Task
。
button.Click += delegate { BeginInvoke(new UiUpdate(delegate { Thread.Sleep(500); // Do Stuff After Sleep };)) };
private delegate void UiUpdate();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.