Alternative to Thread.Sleep in windows Form apart from Timer

走远了吗. 提交于 2019-12-12 10:27:05

问题


I am using Thread.Sleep in windows form C#. using which results in Not responding of Form. Using Timer is also not serving my purpose.

Sample Code:

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

Using above Code results in form irresponsiveness. Using Timer gonna result in Nested Timers. and Not fessable in my case. Please tell me an alternative in windows form. Want the specific pause between commands.


回答1:


The easiest option is to use this model:

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

If you don't have access to C# 5.0 you can do this in 4.0. You'll need to start with your own Delay method, as one doesn't exist in .NET 4.0:

public static Task Delay(int milliseconds)
{
    var tcs = new TaskCompletionSource<bool>();
    var timer = new System.Threading.Timer(o => tcs.SetResult(false));
    timer.Change(milliseconds, -1);
    return tcs.Task;
}

Using that we can now write:

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

That is pretty similar to the code that the first snippet will be compiled into, but clearly that first one is much prettier, so you should use it if at all possible.

If we go back to C# 3.0 then we lose access to the Task, this means that we're back to using timers and callbacks. We'll start with this simple helper method to handle managing the task for us:

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

Then we can just nest calls to this:

ExecuteIn(1000, () =>
{
    GotoMeasurementMode(3000);
    ExecuteIn(3000, () =>
    {
        query(device.Text);
        ExecuteIn(7000, () => StopMeasurement());
    });
});

While it's possible to re-create a Task in C# 3.0 (it doesn't leverage any of the 4.0 language features) and there are existing libraries that do that, that would be somewhat more involved.




回答2:


Put the above code in a background thread, that way it won't block the UI thread. Assuming your methods in between the waits require UI access, they can use Control.BeginInvoke to make an update on the UI thread.




回答3:


you should consider a BackgroundWorker.

Currently only the .NET framework 4.5 supports the async-await mechanism.

if you're looking at solution backward compatible you should check out this link on CodeProject.

the Background worker will execute your tasks asynchronously in a separate thread context for long running process, keeping your UI responsiveness,

Hope it helps



来源:https://stackoverflow.com/questions/16819447/alternative-to-thread-sleep-in-windows-form-apart-from-timer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!