替代Thread.Sleep在Windows窗体中除了Timer
我在Windows窗体C#中使用Thread.Sleep。 使用哪个导致没有响应表格。 使用Timer也不符合我的目的。
示例代码:
if(......) // There are many if with difrent components and many Thread.sleep { button.visible=true; Thread.sleep(1000); GotoMeasurementMode(3000); Thread.sleep(3000); query(device.Text); Thread.sleep(7000); StopMeasurement(); Thread.sleep(4000); }
使用上面的代码导致forms无响应。 使用Timer会产生嵌套计时器。 在我的情况下并不是可怜的。 请告诉我windows窗体的替代方案。 想要命令之间的特定暂停。
最简单的选择是使用此模型:
public async void button1_Click(object sender, EventArgs args) { if(condition) { button.visible=true; await Task.Delay(1000); GotoMeasurementMode(3000); await Task.Delay(3000); query(device.Text); await Task.Delay(7000); StopMeasurement(); await Task.Delay(4000); } }
如果您无法访问C#5.0,则可以在4.0中执行此操作。 您需要从自己的Delay
方法开始,因为.NET 4.0中不存在这种方法:
public static Task Delay(int milliseconds) { var tcs = new TaskCompletionSource(); var timer = new System.Threading.Timer(o => tcs.SetResult(false)); timer.Change(milliseconds, -1); return tcs.Task; }
使用它我们现在可以写:
Delay(1000) .ContinueWith(t => GotoMeasurementMode(3000), TaskScheduler.FromCurrentSynchronizationContext()) .ContinueWith(t => Delay(3000)).Unwrap() .ContinueWith(t => query(device.Text), TaskScheduler.FromCurrentSynchronizationContext()) .ContinueWith(t => Delay(7000)).Unwrap() .ContinueWith(t => StopMeasurement(), TaskScheduler.FromCurrentSynchronizationContext()) .ContinueWith(t => Delay(4000)).Unwrap();
这与第一个代码段编译成的代码非常相似,但显然第一个代码段更漂亮,所以你应该尽可能地使用它。
如果我们回到C#3.0,那么我们将无法访问Task
,这意味着我们将重新使用计时器和回调。 我们将从这个简单的帮助方法开始,为我们处理任务:
public static void ExecuteIn(int milliseconds, Action action) { var timer = new System.Windows.Forms.Timer(); timer.Tick += (s, e) => { action(); timer.Stop(); }; timer.Interval = milliseconds; timer.Start(); }
然后我们可以嵌套调用:
ExecuteIn(1000, () => { GotoMeasurementMode(3000); ExecuteIn(3000, () => { query(device.Text); ExecuteIn(7000, () => StopMeasurement()); }); });
虽然可以在C#3.0中重新创建一个Task
(它没有利用任何4.0语言function),并且有现有的库可以做到这一点,但这会更多地涉及到。
将上面的代码放在后台线程中,这样就不会阻塞UI线程。 假设您在等待之间的方法需要UI访问,他们可以使用Control.BeginInvoke在UI线程上进行更新。
你应该考虑一个BackgroundWorker 。
目前只有.NET framework 4.5支持async-await机制。
如果您正在寻找向后兼容的解决方案,您应该在CodeProject上查看此链接。
后台工作程序将在一个单独的线程上下文中异步执行您的任务,以便长时间运行进程,保持您的UI响应能力,
希望能帮助到你