取消调用事件

时间:2017-08-16 06:13:02

标签: c# uwp async-await cancellationtokensource taskcompletionsource

我有一个无头UWP应用程序,它使用外部库连接到串行设备并发送一些命令。它运行一个无限循环(同时为true),循环之间有10分钟的暂停。测量过程大约需要4分钟。 外部库需要运行3次测量,然后通过引发事件发出信号。当事件被提升第四次我知道我可以返回结果。

4小时后(+/-几秒钟),图书馆停止提升事件(通常会将事件提高一到两次,然后停止,没有错误,没有任何错误)。

我在一个CancellationTokenSource下面的DoMeasureAsync()中实现了,它应该在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();
        }
    }

1 个答案:

答案 0 :(得分:1)

经过更多测试后,我得出的结论是没有内存泄漏,并且所有对象都已丢弃。取消效果也很好。

到目前为止,我的问题似乎来自于Raspberry Pi上无头应用程序的执行。虽然我使用的是deferral = taskInstance.GetDeferral();似乎执行在某个时刻停止了......

我会测试更多并返回结果(可能在新帖子中,但我也会在此处添加链接)。

修改: 这是新帖子:UWP - Headless app stops after 3 or 4 hours

编辑2: 问题来自我必须使用的第三方库,它必须与无头应用程序不同地调用。如果SynchronizationContext.Current为null,则在内部创建自己的TaskScheduler。