Search code examples
c#foreachasync-awaitbackgroundworker

Background Object Triggers "RunWorkerCompleted" event When Process Not Finished


My Background Worker object triggers the "RunWorkerCompleted" event when the foreach loop in it has just returned 1 time, no matter how long the loop rotates after that trigger, never triggers it again (I'm talking about the current session). Why does he do that? How to fix it?

("private async void" keywords are used on Background DoWork event, there is one foreach loop, there is a method triggered by "await" in that loop.)

One example;

private async void bgwCheckFiles_DoWork(object sender, DoWorkEventArgs e)
{
    string a;
    foreach (string s in lblist.Items) { a = await getMD5HashFromFile2(s); }
}

private void bgwCheckFiles_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{ MessageBox.Show("Process ended."); }

When this code is not yet finished, system is "Process ended." giving this message.


Solution

  • Because you're using an async void method, the execution of that method ends at the first blocking await whish means that the work is considered completed for the BackgroundWorker.

    If you're already using asynchronous APIs, you have no need for the BackgroundWorker. You just need something like this:

    private async Task GetMD5HashFromFilesAsync()
    {
        foreach (string s in lblist.Items)
        {
            await getMD5HashFromFile2(s).ConfigureAwait(false);
        }
    }
    

    And, supposing you're calling it from an event handler:

    private async void bgwCheckFiles_RunWorkerCompleted(object sender, EventArgs e)
    {
        await GetMD5HashFromFilesAsync();
        MessageBox.Show("Process ended.");
    }