2

取消異步方法我有一個使用一個外部庫連接到串行設備,併發送一些命令無頭UWP應用。它運行一個無限循環(while true),循環之間暫停10分鐘。測量過程大約需要4分鐘。 外部庫需要運行3次測量,並在每次測量後通過引發事件發出信號。第四次當事件發生時,我知道我可以返回結果。調用事件

4小時後(+/-幾秒鐘)庫將停止籌款活動(通常是引發事件的一個或2次,然後停止,沒有錯誤,沒有什麼)。

我在DoMeasureAsync()下面的CancellationTokenSource中實現,本應在8分鐘後在TaskCompletionSource上設置IsCancelled屬性,以便任務返回並繼續循環。

問題: 當測量沒有完成(在NMeasureCompletionSource從來沒有得到它的結果在課堂CMeasure設置),從nMeasureCompletionSource任務永遠不會取消。在RespondToCancellationAsync()中定義的委託應該在8分鐘後運行。

如果測量運行正常,我可以在在

taskAtHand.ContinueWith((x) => 

     { 
      Logger.LogDebug("Disposing CancellationTokenSource..."); 
      cancellationTokenSource.Dispose(); 
     }); 

代碼被調用的日誌中看到。

編輯是否有可能在GC 4小時後進來,可能會釋放一些變量和這樣做使得應用無法將命令發送到傳感器? - 這是不是這樣的

缺少什麼我在這裏?

//this gets called in a while (true) loop 
    public Task<PMeasurement> DoMeasureAsync() 
    { 

     nMeasureCompletionSource = new TaskCompletionSource<PMeasurement>(); 

     cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(8)); 

     var t = cMeasure.Run(nitrateMeasureCompletionSource, cancellationTokenSource.Token); 

     var taskAtHand = nitrateMeasureCompletionSource.Task; 
     taskAtHand.ContinueWith((x) => 

     { 
      Logger.LogDebug("Disposing CancellationTokenSource..."); 
      cancellationTokenSource.Dispose(); 
     }); 

     return taskAtHand; 
    } 

    public class CMeasure 
    { 
     public async Task Run(TaskCompletionSource<PMeasurement> tcs, CancellationToken cancellationToken) 
     { 
      try 
      { 
       NMeasureCompletionSource = tcs; 
       CancellationToken = cancellationToken; 

       CancellationToken.Register(async() => await RespondToCancellationAsync(), useSynchronizationContext: false); 

       CloseDevice(); //Closing device if for some reason is still open 
       await Task.Delay(2500); 

       TheDevice = await GetDevice(); 

       measurementsdone = 0; 

       Process(); //start the first measurement 
      } 
      catch (Exception ex) 
      { 
       DisconnectCommManagerAndCloseDevice(); 

       NMeasureCompletionSource.SetException(ex); 
      } 
     } 

     public async Task RespondToCancellationAsync() 
     { 

      if (!NitrateMeasureCompletionSource.Task.IsCompleted) 
      { 
       Logger.LogDebug("Measure Completion Source is not completed. Cancelling..."); 
       NMeasureCompletionSource.SetCanceled(); 
      } 

      DisconnectCommManagerAndCloseDevice(); 

      await Task.Delay(2500); 

     } 

     private void Process() 
     { 

      if (measurementsdone < 3) 
      { 
       var message = Comm.Measure(m); //start a new measurement on the device 
      } 
      else 
      { 
       ... 
       NMeasureCompletionSource.SetResult(result); 
      } 

     } 

     //the method called when the event is raised by the external library 
     private void Comm_EndMeasurement(object sender, EventArgs e) 
     { 
      measurementsdone++; 

      Process(); 
     } 
    } 
+3

「的GC 4小時後進來,可能會釋放一些變量和這樣做使得應用無法將命令發送到傳感器,可以嗎?」 - 你如何得出這個假設?強烈引用的對象不會被GC收集。即使他們願意,那麼你應該得到一些空指針異常或類似的東西。 – Fildor

+0

@Fildor在這一刻我可以想到任何東西:) –

+0

哦,*那*絕望......在這種情況下,我會隔離第三方並在測試項目中測試它的行爲。這個項目不會做任何事情,而是開始處理「在設備上」,看看它是否提高了回調。也許可以測量往返時間。如果這顯示相同的行爲,我會聯繫製造商並尋求幫助。如果它運行正常並且穩定,那麼我會創建一些模擬來代替第三方,這樣您可以更好地調試整體設計。哦,並用伐木膏抹它。您稍後可以再次刪除它,但如果您不知道發生了什麼,請讓代碼告訴您。 – Fildor

回答

1

經過更多的測試後,我得出了沒有內存泄漏並且所有對象都被丟棄的結論。取消也適用。

到目前爲止,看來我的問題來自於樹莓派無頭應用程序的執行。儘管我正在使用deferral = taskInstance.GetDeferral();似乎停止執行在某些點......

我將考驗更多,回來的結果(可能在一個新的職位,但我會在這裏把一個鏈接以及)。

編輯: 這裏是新的職位:UWP - Headless app stops after 3 or 4 hours

編輯2: 問題是由第三方庫,我不得不使用,它必須從一具無頭的應用程序不同的所謂。如果SynchronizationContext.Current爲空,它在內部創建自己的TaskScheduler。