关于 .NET 中的内存泄漏,使用不在 Func 参数列表中的对象的 Func 回调
Func callback using objects not in parameter list of Func in regards to memory leaks in .NET
我下面有一个回调函数,它接受一个 name
的参数。我还有一些来自调用父函数的其他函数。参数 otherGame
、_venueLocationsManager
等是否会导致任何类型的内存泄漏或性能问题,或者这是一个有效的编程设置?
private IEnumerable<ValidateScheduleResult> GetMinimumOverlappingPoolGames(EventScheduleGameLayout gridItem, EventScheduleGameLayout otherGame, EventScheduleTeamLayout otherTeam, int minimumTimeBetweenGames, ValidationScheduleSettingsModel scheduleSettings)
{
Func<string, ValidateScheduleResult> callback = (name) =>
{
return FillGameInformation(new ValidateMinimumTimeBetweenGamesResult(name, otherGame.GetDate(), otherGame.GetTime(), _venueLocationsManager.GetVenueLocationName(otherGame.VenueCourtId), minimumTimeBetweenGames, scheduleSettings.ContestType), gridItem, ValidateItemResult.StatusType.Warning);
};
return GetOverlappingPoolGames(gridItem, otherTeam, callback);
}
回调来自
private IEnumerable<ValidateScheduleResult> GetOverlappingPoolGames(EventScheduleGameLayout gridItem, EventScheduleTeamLayout otherTeam, Func<string, ValidateScheduleResult> callback)
{
var validationScheduleResults = new List<ValidateScheduleResult>();
Action<string> nameCallback = (name) =>
{
validationScheduleResults.Add(callback(name));
};
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.AwayTeam, otherTeam, nameCallback);
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.HomeTeam, otherTeam, nameCallback);
if (gridItem.Matchup.WorkTeam != null)
{
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.WorkTeam, otherTeam, nameCallback);
}
foreach (var validationResult in validationScheduleResults)
yield return validationResult;
}
调用代码
if (scheduleSettings.MinimumTimeBetweenGames.HasValue)
{
// Get Division Teams And Teams Cross Playing
var minimumTimesBetween = GetMinimumTimeBetweenRow(scheduledMatchups, scheduleSettings.MinimumTimeBetweenGames.Value, gridItem.GameDuration, gridItem).Where(q => q != gridItem && (q.Matchup.DivisionId == gridItem.Matchup.DivisionId || ScheduleHelper.HasTeamGame(q.Matchup, gridItem.Matchup) || ScheduleHelper.HasSeededGame(q.Matchup, gridItem.Matchup))).ToList();
foreach (var divisionGame in minimumTimesBetween)
{
validationResults.AddRange(GetMinimumOverlappingPoolGames(gridItem, divisionGame, divisionGame.Matchup.AwayTeam, scheduleSettings.MinimumTimeBetweenGames.Value, scheduleSettings));
validationResults.AddRange(GetMinimumOverlappingPoolGames(gridItem, divisionGame, divisionGame.Matchup.HomeTeam, scheduleSettings.MinimumTimeBetweenGames.Value, scheduleSettings));
}
}
IsPoolGameRestricted
public bool IsPoolGamesRestricted(
EventScheduleTeamLayout currentTeam,
EventScheduleTeamLayout otherTeam,
Action<string> nameCallback)
{
nameCallback?.Invoke(FormatGameName.GetPoolName(currentTeam.PoolNumber, currentTeam.PoolName));
return true;
}
这不会导致任何内存泄漏,因为 .NET 运行时将为您管理内存分配,并确保这些对象只要仍在使用中就不会被清除。
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/
使用回调与直接调用函数的性能应该非常相似,如果不一样的话。
作为旁注,您可能还想看看如何使用 async/await,而不是依赖回调来延迟执行,它提供了一个替代方案,而且可以说更易于阅读。
我下面有一个回调函数,它接受一个 name
的参数。我还有一些来自调用父函数的其他函数。参数 otherGame
、_venueLocationsManager
等是否会导致任何类型的内存泄漏或性能问题,或者这是一个有效的编程设置?
private IEnumerable<ValidateScheduleResult> GetMinimumOverlappingPoolGames(EventScheduleGameLayout gridItem, EventScheduleGameLayout otherGame, EventScheduleTeamLayout otherTeam, int minimumTimeBetweenGames, ValidationScheduleSettingsModel scheduleSettings)
{
Func<string, ValidateScheduleResult> callback = (name) =>
{
return FillGameInformation(new ValidateMinimumTimeBetweenGamesResult(name, otherGame.GetDate(), otherGame.GetTime(), _venueLocationsManager.GetVenueLocationName(otherGame.VenueCourtId), minimumTimeBetweenGames, scheduleSettings.ContestType), gridItem, ValidateItemResult.StatusType.Warning);
};
return GetOverlappingPoolGames(gridItem, otherTeam, callback);
}
回调来自
private IEnumerable<ValidateScheduleResult> GetOverlappingPoolGames(EventScheduleGameLayout gridItem, EventScheduleTeamLayout otherTeam, Func<string, ValidateScheduleResult> callback)
{
var validationScheduleResults = new List<ValidateScheduleResult>();
Action<string> nameCallback = (name) =>
{
validationScheduleResults.Add(callback(name));
};
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.AwayTeam, otherTeam, nameCallback);
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.HomeTeam, otherTeam, nameCallback);
if (gridItem.Matchup.WorkTeam != null)
{
_eventScheduleValidatorsService.PoolGamesValidator.IsPoolGamesRestricted(gridItem.Matchup.WorkTeam, otherTeam, nameCallback);
}
foreach (var validationResult in validationScheduleResults)
yield return validationResult;
}
调用代码
if (scheduleSettings.MinimumTimeBetweenGames.HasValue)
{
// Get Division Teams And Teams Cross Playing
var minimumTimesBetween = GetMinimumTimeBetweenRow(scheduledMatchups, scheduleSettings.MinimumTimeBetweenGames.Value, gridItem.GameDuration, gridItem).Where(q => q != gridItem && (q.Matchup.DivisionId == gridItem.Matchup.DivisionId || ScheduleHelper.HasTeamGame(q.Matchup, gridItem.Matchup) || ScheduleHelper.HasSeededGame(q.Matchup, gridItem.Matchup))).ToList();
foreach (var divisionGame in minimumTimesBetween)
{
validationResults.AddRange(GetMinimumOverlappingPoolGames(gridItem, divisionGame, divisionGame.Matchup.AwayTeam, scheduleSettings.MinimumTimeBetweenGames.Value, scheduleSettings));
validationResults.AddRange(GetMinimumOverlappingPoolGames(gridItem, divisionGame, divisionGame.Matchup.HomeTeam, scheduleSettings.MinimumTimeBetweenGames.Value, scheduleSettings));
}
}
IsPoolGameRestricted
public bool IsPoolGamesRestricted(
EventScheduleTeamLayout currentTeam,
EventScheduleTeamLayout otherTeam,
Action<string> nameCallback)
{
nameCallback?.Invoke(FormatGameName.GetPoolName(currentTeam.PoolNumber, currentTeam.PoolName));
return true;
}
这不会导致任何内存泄漏,因为 .NET 运行时将为您管理内存分配,并确保这些对象只要仍在使用中就不会被清除。
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/
使用回调与直接调用函数的性能应该非常相似,如果不一样的话。
作为旁注,您可能还想看看如何使用 async/await,而不是依赖回调来延迟执行,它提供了一个替代方案,而且可以说更易于阅读。