Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delay in ContinueWith not working

My question is why the delay method is not working (whole operation is not waiting for 4 sec) and 60% is not showing inside the lable1.

To be more precise the sequence of the operations should be like this and whole operation should take 8 seconds.but it takes 4 seconds, just Thread.Sleep(4000) inside LongTimeMethod1() is working

LongTimeMethod1()//delay for 4 sec,show 60%
delay()//delay for 4 sec 
LongTimeMethod()//40% imidiatly

I know I can write code just with await and async but I want to know what am I doing wrong in this code.

 private void button1_Click(object sender, EventArgs e)
    {
        CallBigMethod();
        label1.Text =@"Waiting ...";
    }
    private async void CallBigMethod()
    {
        var result = await BigMethod();
        label1.Text = result; 


    }
    private Task<string> BigMethod()
    {
        return Task.Factory
         .StartNew(() => LongTimeMethod1())
         .ContinueWith((pre) => Delay())
         .ContinueWith((pre) => LongTimeMethod());
    }     
    private string LongTimeMethod()
    {

        return  "40%...";
    }
    public async Task Delay()
    {

        await Task.Delay(4000);

    }
    private string LongTimeMethod1()
    {
        Thread.Sleep(4000);
        return "60%...";
    }  
like image 813
E_N_Y Avatar asked Sep 25 '15 12:09

E_N_Y


1 Answers

The Task returned by .ContinueWith((pre) => Delay()) is actually a Task<Task>. That continuation will be finished as soon as it finishes starting the delay, but since the delay is asynchronous, it doesn't wait for it to finish. You need to unwrap the Task<Task> so that you're adding a continuation to the inner task and have your program continue on when the delay finishes, rather than when it finishes being started.

Fortunately there's an Unwrap method that just does all of this for us.

private Task<string> BigMethod()
{
    return Task.Factory
     .StartNew(() => LongTimeMethod1())
     .ContinueWith((pre) => Delay())
     .Unwrap()
     .ContinueWith((pre) => LongTimeMethod());
}    

That said, the whole thing is much simpler when the method is async, rather than using ContinueWith:

private Task<string> BigMethod()
{
    await Task.Run(() => LongTimeMethod1());
    await Delay();
    return await Task.Run(() => LongTimeMethod());
} 
like image 133
Servy Avatar answered Sep 28 '22 13:09

Servy