简体   繁体   中英

C# Tasks with Progress Reporting and Return Value Not Reporting Progress

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!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM