1

I am trying to run a task in a method and have the method return a value. The reason I am using a task is because I need progress reporting.

This was my original strategy

   private async void CallLongRunningTask()
   {
       string fileName = "TestFN";
       Progress<string> progress = new Progress<string>();
       progress.ProgressChanged += (_, newText) => lbl.Text=newText;
       bool retVal = await Task.Run(() => LongRunningTask(fileName, progress));
       Task.WaitAll();
       // do some other stuff    

   }

   public bool LongRunningTask(string fn, IProgress<string> progress)
   {
       // long running task with progress report
         while (i < 100000000)
        {
            i++;
            if (i % 10000 == 0)
            {
                progress.Report("Processing "+i.ToString());
            }
        }
        return true;
   }

As expected, it blew through the WaitAll, went back to the prior method.

So, I tried this:

got rid of async in the signature

bool retVal = Task.Run(() => LongRunningTask(fileName, progress));
bool retVal = Task.Run(async () => LongRunningTask(fileName, progress));

Both instances, I lost my progress.

So I tried to change my calling program:

   Task.Run(() => CallLongRunningTask()).Wait();

That broke my progress reporting because my progress reporting updates a label on the form so there was some kind of cross thread contamination.

I have read and tried all the relevant similar problems/solutions. This seems so simple but clearly I am missing something. The entire Task() and async thing seems to be on a level of abstraction that I can't seem to grasp no matter how many times I read Stephen Cleary's book.

Any thoughts or ideas or help in any way, would be greatly appreciated!

6
  • 2
    Don't use async void. It's only meant for event handlers. If you don't want to return a result use async Task Commented Oct 31, 2018 at 15:24
  • 3
    BTW a Task.WaitAll() is meaningless. WaitAll waits only for its arguments to complete but you didn't provide any. You don't need it either since await awaits for the task to complete. The problem is that the entire method is a fire-and-forget method due to async void Commented Oct 31, 2018 at 15:26
  • Thanks for your help. I changed the signature from Void to Task so it is updating progress but still flying through the WaitAll I think because it is async and I am not able to figure out how to get a proper return value. I will try moving the stuff that needs doing after the Task() to the calling method and trying to await from the calling method. Commented Oct 31, 2018 at 16:08
  • 2
    There is no need for the WaitAll as already mentioned. Commented Oct 31, 2018 at 16:13
  • 1
    async spreads all the way up. you need to await everything including the calling method. You have not shown how it is being called so there is not much else we can do in terms of helping as this appears to be an XY problem Commented Oct 31, 2018 at 16:20

1 Answer 1

4

There is no need for the WaitAll as already mentioned.

private async Task CallLongRunningTask() {
    string fileName = "TestFN";
    Progress<string> progress = new Progress<string>();
    progress.ProgressChanged += (_, newText) => lbl.Text=newText;

    //waiting here for long running task to finish
    bool retVal = await Task.Run(() => LongRunningTask(fileName, progress));

    // do some other stuff after waiting
}

async-await spreads all the way up. You need to await everything including the calling method.

await CallLongRunningTask();

and so on.

If calling from an event handler, that is the only exception where async void can be used

private async void OnSomeHandler(object sender, EventArgs args) {
    //...

    await CallLongRunningTask();

    //...
}

Reference Async/Await - Best Practices in Asynchronous Programming

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. The problem is that the method is async so it's returning to the calling method on the await. What I really want to do is not have it async and have the task wait and report progress. I haven't been able to figure out how to get progress reporting to work without making the method async. I think it must be something in defining the Task but I haven't figured it out.
@Missy await doesn't cause anything to return. Most likely you've forgotten to await the method itself

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.