Reputation: 311
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
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
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
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