繁体   English   中英

异步任务内存泄漏

[英]Async task memory leak

我只是对在设备上运行的UWP应用程序进行性能分析,以尝试诊断观察到的内存泄漏。

使用快照,我发现我有越来越多的Task对象,这些对象似乎是由引发日志事件的内部组件创建的。

这是一个比较快照和看起来正在泄漏的对象的屏幕截图。

内存快照 根目录

我有两个绑定到OnLogReceived的事件侦听器; 他们看起来像这样:

ApplicationContext.Current.LoggerContext.OnLogReceived += LoggerContext_OnLogReceived;
ApplicationContext.Current.LoggerContext.OnLogReceived += (logLevel, timestamp, message) => RemoteLogHelper.SendMessage(logLevel, message);

这是第一个处理程序的定义。 这将在屏幕上的滚动查看器中显示日志,并将条目截断为1000。LogEntryModel通过ViewModelBase实现INotifyPropertyChanged,以避免泄漏PropertyChanged。

private async void LoggerContext_OnLogReceived(LogLevel logLevel, DateTime timestamp, string message)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            var entry = new LogEntryModel
            {
                Message = string.Format("[{0:h:mm:ss tt}] {1}", timestamp, message)
            };
            entry.SetDispatcher(ApplicationContext.Current.Dispatcher);

            lock (ApplicationContext.Current.ReceiverDetails.Log)
            {
                ApplicationContext.Current.ReceiverDetails.Log.Add(entry);

                while (ApplicationContext.Current.ReceiverDetails.Log.Count > 1000)
                {
                    ApplicationContext.Current.ReceiverDetails.Log.RemoveAt(0);
                }
            }

            if (!uxPreventLogFromScrolling.IsChecked ?? false)
            {
                LogScrollViewer.ChangeView(0.0d, double.MaxValue, 1.0f);
            }
        });
    }

发送消息处理程序(2)会将日志行发送到远程API(如果为此设备启用了远程日志记录)以进行调试。 我们希望这是一发不可收拾的事情,这意味着我们不想等待日志成功发送到端点。

public static async void SendMessage(LogLevel logLevel, string message)
    {
        if (!IsEnabled())
            return;

        await Task.Run(() =>
        {
            try
            {
                ApplicationContext.Current.ApiClient.PostAsync<LogRequestModel, object>("/api/remote/receiver/log", new LogRequestModel { MacAddress = MacAddress, Text = message });
            }
            catch (Exception)
            {
                ; // we tried
            }
        });
    }

将此方法更改为以下定义不会更改行为(仍然显示相似的快照结果)

public static async void SendMessage(LogLevel logLevel, string message)
    {
        if (!IsEnabled())
            return;

        try
        {
            await ApplicationContext.Current.ApiClient.PostAsync<LogRequestModel, object>("/api/remote/receiver/log", new LogRequestModel { MacAddress = MacAddress, Text = message });
        }
        catch (Exception)
        {
            ; // we tried
        }

    }

谁能说出泄漏的原因以及如何避免泄漏? 通过研究,我认为我不需要处理任务,这里的所有事情看起来都应该在完成后自动清理。 但是,我可以肯定地看到内存使用量正在增长,快照证实了这一点。

如果有人遇到此问题,请在此处记录答案。 我们使用.ContinueWith来防止任务泄漏

资料来源: http : //stackoverflow.com/a/15524271/647728

    public static void SendMessage(LogLevel logLevel, string message)
    {
        if (!IsEnabled())
            return;

        //http://stackoverflow.com/a/15524271/647728
        ApplicationContext.Current.ApiClient.PostAsync<LogRequestModel, object>("/api/remote/receiver/log", new LogRequestModel { MacAddress = MacAddress, Text = message }).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnFaulted);

    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM