取消异步方法我有一个使用一个外部库连接到串行设备,并发送一些命令无头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();
}
}
“的GC 4小时后进来,可能会释放一些变量和这样做使得应用无法将命令发送到传感器,可以吗?” - 你如何得出这个假设?强烈引用的对象不会被GC收集。即使他们愿意,那么你应该得到一些空指针异常或类似的东西。 – Fildor
@Fildor在这一刻我可以想到任何东西:) –
哦,*那*绝望......在这种情况下,我会隔离第三方并在测试项目中测试它的行为。这个项目不会做任何事情,而是开始处理“在设备上”,看看它是否提高了回调。也许可以测量往返时间。如果这显示相同的行为,我会联系制造商并寻求帮助。如果它运行正常并且稳定,那么我会创建一些模拟来代替第三方,这样您可以更好地调试整体设计。哦,并用伐木膏抹它。您稍后可以再次删除它,但如果您不知道发生了什么,请让代码告诉您。 – Fildor