简体   繁体   中英

RunWorkerCompleted fired before async void Dowork event

I'm using A background worker for BLE RSSI level test.

my problem is that RunWorkerCompleted event is fired immediately, way before DoWork done it's operation.

most of the DoWork event operation is to create an advertisement watcher and wait for Signal from A Bluetooth low energy device. the signal level will be updated fromthe main thread and handling of the result will be on the background worker.

here is when I call the Background worker:

 ...
  worker = new BackgroundWorker();
        worker.DoWork += callTestBLE;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.RunWorkerAsync(RSSI_Label);
  }

The event handlers:

private async void callTestBLE(object sender, DoWorkEventArgs e)
    {
            BluetoothLEAdvertisementWatcher watcher1 ;
            BluetoothLEAdvertisementFilter advertisementFilter1;
            int rssiRetries1 = RSSIRETRIES;
            RssiValue = "";

            advertisementFilter1 = new BluetoothLEAdvertisementFilter();
            try
            {
                advertisementFilter1.Advertisement.LocalName = myUswm.getAdvetrismentName();
                checkRSSI = true;
            }
            catch (Exception) { checkRSSI = false; return; }

            watcher1 = new BluetoothLEAdvertisementWatcher(advertisementFilter);
            watcher1.ScanningMode = BluetoothLEScanningMode.Active;
            watcher1.Received += OnAdvertisementReceived;
            // Wait 5 seconds to make sure the device is really out of range
            watcher1.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
            watcher1.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);

            try
            {
                watcher1.Start(); 
                await testBLEAsync();
                if (myUswm.getConnectionStatus() == DISCONNECTED)
                {
                    checkNextUUTClick(new object(), new RoutedEventArgs()); return;
                }
                for (int i = 0; i < 5; i++)
                {
                    // if (RssiSamplesNum <= 0 || --rssiRetries < 0)
                    if (RssiSamplesNum <= 0 || --rssiRetries1 < 0)
                    {
                        //serviceList.Clear();
                        watcher1.Stop();
                        rssiRetries1 = RSSIRETRIES;
                        RssiSamplesNum1 = numOfAdvertismentSamples;
                        break;
                    }
                    else
                    {
                       ((Label)e.Argument).Content = RssiValue;
                        /*RSSI_Label.Dispatcher.Invoke(new Action(() =>
                        { RSSI_Label.Content = RssiValue; }));*/
                    }
                    Thread.Sleep(2000);
                  }    
            }
    catch (Exception err) { }
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       finalizeBleTest();
    }

Thanks for any help!

The problem here with the async and await . BackgroundWorker is a bit outdated and do not support asynchronous code. So when you await for testBLEAsync call, callTestBLE method finishes and at that moment you have your RunWorkerCompleted event called, while actual code continue to work in the background.

So simplest solution is to completely remove async / await from your code and everything should work as expected, or, alternatively, you can rewrite your code using tasks and task continuations.

I agree with the other answer that BackgroundWorker is not compatible with async / await . However, I disagree that the simplest solution is to remove async in favor of BackgroundWorker . IMO, the superior solution (also resulting in simpler code) is to remove BackgroundWorker in favor of async ; specifically, to replace the outdated BackgroundWorker with the superior Task.Run :

// `worker` is now `Task`.
await Task.Run(() => callTestBLE());
finalizeBleTest();

where the signature of callTestBLE is async Task , not async void .

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