2017-05-24 3 views
0

BLE RSSI 레벨 테스트를 위해 백그라운드 작업자를 사용 중입니다.Async 전에 RunWorkerCompleted 해지 Dowork 이벤트

제 문제는 DoWork가 작업을 완료하기 전에 RunWorkerCompleted 이벤트가 즉시 발생한다는 것입니다.

DoWork 이벤트 작업의 대부분은 광고 감시자를 만들고 Bluetooth 저에너지 장치의 신호를 기다리는 것입니다. 신호 레벨이 메인 스레드에서 업데이트되고 결과 처리가 백그라운드 작업자에게 수행됩니다.

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

이벤트 핸들러 : 어떤 도움

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(); 
    } 

덕분에 나는 배경 노동자를 호출 할 때 여기

입니다!

+0

UI 스레드가 아니기 때문에 백그라운드 작업자 DoWork 스레드에서 UI 요소와 상호 작용하거나 (MessageBox.Show를 호출하면 안 됨) 문제가 발생할 수 있습니다. –

+0

당신이 맞습니다, 코드가 편집되었습니다 –

+1

호출 코드가 완료를 추적 할 수단이 없기 때문에 Fire & * Forget * 코드에'async void'를 사용해야합니다. 그래서'DoWork' 메소드가'async'가되어서는 안된다. 'BackgroundWorker' *를 사용하거나'async' /'await'를 사용하십시오. 그러나 일반적으로 이들을 결합하지 마십시오. –

답변

0

asyncawait의 문제가 여기에 있습니다. BackgroundWorker는 약간 구식이며 비동기 코드를 지원하지 않습니다. 따라서 testBLEAsync 호출을 기다리는 경우 callTestBLE 메서드가 완료되고 그 순간에 RunWorkerCompleted 이벤트가 호출되는 반면 실제 코드는 백그라운드에서 계속 작동합니다.

코드에서 async/await을 완전히 제거하면 모든 것이 예상대로 작동하거나 또는 작업 및 작업 계속을 사용하여 코드를 다시 작성할 수 있습니다.

0

나는 BackgroundWorkerasync/await과 호환되지 않는다는 다른 대답에 동의합니다. 그러나 가장 간단한 해결책은 async을 제거하여 BackgroundWorker을 삭제하는 것입니다. IMO, 더 우수한 해결책은 더 간단한 코드로 결과는 BackgroundWorker을 제거하여 async을 얻는 것입니다. 구체적으로 replace the outdated BackgroundWorker with the superior Task.Run : callTestBLE의 서명 async Task하지 async void이다

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

.