I was putting together a small little demo to take a long running method simulated with a Thread.Sleep()
and wanted to add async to easily go from a synchronous process to an async one. Here's the initial code:
private void button1_Click(object sender, EventArgs e)
{
LongProcess();
}
private void LongProcess()
{
for (int i = 0; i < 33; i++)
{
progressBar1.Value += 3;
Thread.Sleep(1000);
}
progressBar1.Value += 1;
}
I was thinking I could simply change the Thread.Sleep(1000)
into a new Task(()=>Thread.Sleep(1000))
, like so:
private void button1_Click(object sender, EventArgs e)
{
LongProcess();
}
private async void LongProcess()
{
for (int i = 0; i < 33; i++)
{
progressBar1.Value += 3;
await new Task(()=>Thread.Sleep(1000));
}
progressBar1.Value += 1;
}
However this never returns to the loop after the first await. If I change the Thread.Sleep to a Task.Delay everything works, but I don't understand why my code doesn't work. I assume something is getting blocked forever, but it doesn't quite make sense. Can anyone explain how my code works, and a possible solution without changing to Task.Delay (just so I can get another perspective of how this works)?
Task.Delay
isn't same as staring a Task with Thread.Sleep
. Task.Delay
uses Timer
internally and thus it doesn't blocks any thread, however starting a new Task with Thread.Sleep
blocks the thread (typically Threadpool thread).
In your example you never started the Task
. Creating a Task
with constructor will return a Unstarted
task needs to be started with a call to Start
method. Otherwise it will never complete(because you never started it).
However calling Task.Start
is discouraged, You can call Task.Factory.StartNew(()=> Thread.Sleep(1000))
or Task.Run(()=> Thread.Sleep(1000))
if you want to waste a resource.
Also, be aware that StartNew is dangerous, you should prefer Task.Run
over StartNew
unless there's a compelling reason to do so.