我只是在试图诊断观察到的内存泄漏的设备上运行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
}
}
任何人都可以找出泄漏的原因以及我如何避免泄漏吗? 从研究来看,我认为我不需要处理任务,这里的所有内容看起来都应该在完成后自动清理。 但是我可以肯定地看到内存使用量在增长,而快照确认了这一点。
答案 0 :(得分:1)
在此处记录答案,以防其他人遇到该问题。 我们使用.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);
}
}