UWP-无头应用程式会在3或4小时后停止

人气:118 发布:2022-10-16 标签: c# uwp headless

问题描述

我有一个无头的UWP应用,应该每10分钟从传感器获取数据并将其发送到云中. 当我从Raspberry Pi上的无头应用程序运行代码时,它会在3或4个小时后停止测量,没有错误(我有很多日志).恰好是3或4个小时.如果我在8点11或12点启动应用程序,它将停止...

I have a headless UWP app that is supposed to get data from a sensor every 10 minutes and send it to the cloud. When I run the code from the headless app on the Raspberry Pi it stops measuring after 3 or 4 hours, no error (I have a lot of logs). It is exactly 3 or 4 hours. If I start the app at 8, at 11 or 12 it just stops...

它似乎停止了,因为我有取消令牌,该令牌在测试中运行良好,但是这里不再触发.在设备门户"中的应用程序管理器"上,该应用程序正在运行.

It looks like it is stopped because I have cancellation token in place that worked well in tests, but here it is not firing anymore. On the App manager in the Device Portal it appears that the app is running.

在设备门户网站的性能"页面上,我还注意到在测量过程中内存减少了约8 MB.

I also noticed in the Performance page in the Device Portal that the memory goes down with about 8 MB during the measurements.

奇怪的是,我在RPi和笔记本电脑上从带有头部的应用程序中运行了相同的代码,并且运行得非常好.在我停止之前,它连续工作了16个小时以上.在笔记本电脑和RPi上都没有内存问题,该应用在整个期间使用了相同数量的RAM.

The strange thing is that I ran the same code from a headed app on the RPi and on a laptop and it went very well. It worked continuously for over 16 hours until I stopped it. On both the laptop and the RPi there was no memory issue, the app used the same amount of RAM over the whole period.

作为无头应用程序运行时,什么可能导致此行为?

这是我从无头应用程序中调用代码的方式:

Here is how I call the code from the headless app:

BackgroundTaskDeferral deferral;
        private ISettingsReader settings;
        private ILogger logger;
        private IFlowManager<PalmSenseMeasurement> flow;
        private IServiceProvider services;
        IBackgroundTaskInstance myTaskInstance;

        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            taskInstance.Canceled += TaskInstance_Canceled;

            deferral = taskInstance.GetDeferral();

            myTaskInstance = taskInstance;

            try
            {
                SetProperties();

                var flowTask = flow.RunFlowAsync();

                await flowTask;
            }
            catch (Exception ex)
            {

                logger.LogCritical("#####---->Exception occured in StartupTask (Run): {0}", ex.ToString());
            }

        }

        private void SetProperties()
        {
            services = SensorHubContainer.Services;

            settings = services.GetService<ISettingsReader>();

            flow = services.GetService<IFlowManager<PalmSenseMeasurement>>();

            logger = services.GetService<ILogger<StartupTask>>();
        }

        private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {   
            logger.LogDebug("StartupTask.TaskInstance_Canceled() - {0}", reason.ToString());
            deferral.Complete();
        }

这是我从标题应用程序中调用代码的方式:

And here is how I call the code from the headed app:

private async Task GetMeasurementsAsync()
        {

            try
            {

                flow = services.GetService<IFlowManager<PalmSenseMeasurement>>();

                await flow.RunFlowAsync();

            }
            catch (Exception ex)
            {

                Measurements.Add(new MeasurementResult() { ErrorMessage = ex.Message });
            }

        }

RunFlowAsync方法如下:

The RunFlowAsync method looks like this:

public async Task RunFlowAsync()
        {

            var loopInterval = settings.NoOfSecondsForLoopInterval;


            while (true)
            {
                try
                {
                    logger.LogInformation("Starting a new loop in {0} seconds...", loopInterval);

                    //check for previous unsent files
                    await resender.TryResendMeasuresAsync();

                    await Task.Delay(TimeSpan.FromSeconds(loopInterval));

                    await DoMeasureAndSend();

                    logger.LogInformation("Loop finished");


                }
                catch (Exception ex)
                {
                    logger.LogError("Error in Flow<{0}>! Error {1}", typeof(T).FullName, ex);
#if DEBUG
                    Debug.WriteLine(ex.ToString());
#endif
                }
            }
        }

推荐答案

问题出在我必须使用的第3方库中,而且它的调用方式与无头程序不同. 如果SynchronizationContext.Current为null,则在内部创建它自己的TaskScheduler.

The problem was from a 3rd party library that I had to use and it had to be called differently from a headless app. Internally it was creating its own TaskScheduler if SynchronizationContext.Current was null.

749