user1747819
user1747819

Reputation: 311

Alternative to Thread.Sleep in windows Form apart from Timer

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.

Upvotes: 0

Views: 9277

Answers (3)

Servy
Servy

Reputation: 203802

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.

Upvotes: 13

codingadventures
codingadventures

Reputation: 2952

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

Upvotes: 0

Deeko
Deeko

Reputation: 1539

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.

Upvotes: 1

Related Questions