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。