diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 2c6f2c7f6..82294644b 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -150,7 +150,7 @@ namespace Emby.Server.Implementations /// Instance of the interface. /// Instance of the interface. /// The interface. - public ApplicationHost( + protected ApplicationHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index a107e7a52..09429c73f 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Channels /// /// The LiveTV channel manager. /// - public class ChannelManager : IChannelManager + public class ChannelManager : IChannelManager, IDisposable { private readonly IUserManager _userManager; private readonly IUserDataManager _userDataManager; @@ -52,6 +52,7 @@ namespace Emby.Server.Implementations.Channels private readonly IMemoryCache _memoryCache; private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; + private bool _disposed = false; /// /// Initializes a new instance of the class. @@ -1213,5 +1214,31 @@ namespace Emby.Server.Implementations.Channels return result; } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and optionally managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _resourcePool?.Dispose(); + } + + _disposed = true; + } } } diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index e5dde48d8..cfd08e653 100644 --- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Channels public string Key => "RefreshInternetChannels"; /// - public async Task Execute(CancellationToken cancellationToken, IProgress progress) + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var manager = (ChannelManager)_channelManager; diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 80b8f9ebf..9d4c21e01 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -390,6 +390,7 @@ namespace Emby.Server.Implementations.Data return userData; } +#pragma warning disable CA2215 /// /// /// There is nothing to dispose here since and @@ -398,6 +399,10 @@ namespace Emby.Server.Implementations.Data /// protected override void Dispose(bool dispose) { + // The write lock and connection for the item repository are shared with the user data repository + // since they point to the same database. The item repo has responsibility for disposing these two objects, + // so the user data repo should not attempt to dispose them as well } +#pragma warning restore CA2215 } } diff --git a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs index 1c69056d2..6fc7f1ac3 100644 --- a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs @@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Images { private readonly ILibraryManager _libraryManager; - public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + protected BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { _libraryManager = libraryManager; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 064fd2372..637f757f8 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1007,14 +1007,8 @@ namespace Emby.Server.Implementations.Library return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId); } - /// - /// Validate and refresh the People sub-set of the IBN. - /// The items are stored in the db but not loaded into memory until actually requested by an operation. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task ValidatePeople(CancellationToken cancellationToken, IProgress progress) + /// + public Task ValidatePeopleAsync(IProgress progress, CancellationToken cancellationToken) { // Ensure the location is available. Directory.CreateDirectory(_configurationManager.ApplicationPaths.PeoplePath); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index f1d4b6097..582e61d79 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -24,7 +24,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV { - public class EncodedRecorder : IRecorder + public class EncodedRecorder : IRecorder, IDisposable { private readonly ILogger _logger; private readonly IMediaEncoder _mediaEncoder; @@ -36,6 +36,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private Stream _logFileStream; private string _targetPath; private Process _process; + private bool _disposed = false; public EncodedRecorder( ILogger logger, @@ -323,5 +324,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logger.LogError(ex, "Error reading ffmpeg recording log"); } } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and optionally managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _logFileStream?.Dispose(); + _process?.Dispose(); + } + + _logFileStream = null; + _process = null; + + _disposed = true; + } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index a8440102d..ffa0d9b6a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -28,7 +28,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.Listings { - public class SchedulesDirect : IListingsProvider + public class SchedulesDirect : IListingsProvider, IDisposable { private const string ApiUrl = "https://json.schedulesdirect.org/20141201"; @@ -39,6 +39,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ConcurrentDictionary _tokens = new ConcurrentDictionary(); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private DateTime _lastErrorResponse; + private bool _disposed = false; public SchedulesDirect( ILogger logger, @@ -58,8 +59,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var dates = new List(); - var start = new List { startDateUtc, startDateUtc.ToLocalTime() }.Min().Date; - var end = new List { endDateUtc, endDateUtc.ToLocalTime() }.Max().Date; + var start = new[] { startDateUtc, startDateUtc.ToLocalTime() }.Min().Date; + var end = new[] { endDateUtc, endDateUtc.ToLocalTime() }.Max().Date; while (start <= end) { @@ -822,5 +823,31 @@ namespace Emby.Server.Implementations.LiveTv.Listings return list; } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and optionally managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _tokenSemaphore?.Dispose(); + } + + _disposed = true; + } } } diff --git a/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs b/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs index 15df0dcf1..72bbdd14a 100644 --- a/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs +++ b/Emby.Server.Implementations/LiveTv/RefreshGuideScheduledTask.cs @@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.LiveTv public string Key => "RefreshGuide"; /// - public Task Execute(CancellationToken cancellationToken, IProgress progress) + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var manager = (LiveTvManager)_liveTvManager; diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 299f10544..2c4d6884d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -414,7 +414,7 @@ namespace Emby.Server.Implementations.ScheduledTasks CurrentCancellationTokenSource.CancelAfter(TimeSpan.FromTicks(options.MaxRuntimeTicks.Value)); } - await ScheduledTask.Execute(CurrentCancellationTokenSource.Token, progress).ConfigureAwait(false); + await ScheduledTask.ExecuteAsync(progress, CurrentCancellationTokenSource.Token).ConfigureAwait(false); status = TaskCompletionStatus.Completed; } @@ -757,6 +757,10 @@ namespace Emby.Server.Implementations.ScheduledTasks var trigger = triggerInfo.Item2; trigger.Triggered -= OnTriggerTriggered; trigger.Stop(); + if (trigger is IDisposable disposable) + { + disposable.Dispose(); + } } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index a5786a3d7..0bf0838fa 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -88,13 +88,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public async Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var videos = _libraryManager.GetItemList(new InternalItemsQuery { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs index 79886cb52..776079044 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/CleanActivityLogTask.cs @@ -57,12 +57,12 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks public bool IsLogged => true; /// - public Task Execute(CancellationToken cancellationToken, IProgress progress) + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var retentionDays = _serverConfigurationManager.Configuration.ActivityLogRetentionDays; if (!retentionDays.HasValue || retentionDays < 0) { - throw new Exception($"Activity Log Retention days must be at least 0. Currently: {retentionDays}"); + throw new InvalidOperationException($"Activity Log Retention days must be at least 0. Currently: {retentionDays}"); } var startDate = DateTime.UtcNow.AddDays(-retentionDays.Value); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 0941902fc..03935b384 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -79,19 +79,14 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var minDateModified = DateTime.UtcNow.AddDays(-30); try { - DeleteCacheFilesFromDirectory(cancellationToken, _applicationPaths.CachePath, minDateModified, progress); + DeleteCacheFilesFromDirectory(_applicationPaths.CachePath, minDateModified, progress, cancellationToken); } catch (DirectoryNotFoundException) { @@ -104,7 +99,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks try { - DeleteCacheFilesFromDirectory(cancellationToken, _applicationPaths.TempDirectory, minDateModified, progress); + DeleteCacheFilesFromDirectory(_applicationPaths.TempDirectory, minDateModified, progress, cancellationToken); } catch (DirectoryNotFoundException) { @@ -117,11 +112,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// /// Deletes the cache files from directory with a last write time less than a given date. /// - /// The task cancellation token. /// The directory. /// The min date modified. /// The progress. - private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress progress) + /// The task cancellation token. + private void DeleteCacheFilesFromDirectory(string directory, DateTime minDateModified, IProgress progress, CancellationToken cancellationToken) { var filesToDelete = _fileSystem.GetFiles(directory, true) .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs index fedb5deb0..9739d7327 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -69,13 +69,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { // Delete log files more than n days old var minDateModified = DateTime.UtcNow.AddDays(-_configurationManager.CommonConfiguration.LogFileRetentionDays); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index 099d781cd..e4e565c64 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -78,18 +78,13 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var minDateModified = DateTime.UtcNow.AddDays(-1); progress.Report(50); - DeleteTempFilesFromDirectory(cancellationToken, _configurationManager.GetTranscodePath(), minDateModified, progress); + DeleteTempFilesFromDirectory(_configurationManager.GetTranscodePath(), minDateModified, progress, cancellationToken); return Task.CompletedTask; } @@ -97,11 +92,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// /// Deletes the transcoded temp files from directory with a last write time less than a given date. /// - /// The task cancellation token. /// The directory. /// The min date modified. /// The progress. - private void DeleteTempFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress progress) + /// The task cancellation token. + private void DeleteTempFilesFromDirectory(string directory, DateTime minDateModified, IProgress progress, CancellationToken cancellationToken) { var filesToDelete = _fileSystem.GetFiles(directory, true) .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs index 35a4aeef6..98e45fa46 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs @@ -69,13 +69,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { _logger.LogInformation("Optimizing and vacuuming jellyfin.db..."); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index 34780111b..7d60ea731 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -62,15 +62,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Returns the task to be executed. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { - return _libraryManager.ValidatePeople(cancellationToken, progress); + return _libraryManager.ValidatePeopleAsync(progress, cancellationToken); } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index b3973cecb..443649e6e 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -68,13 +68,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }; } - /// - /// Update installed plugins. - /// - /// The cancellation token. - /// The progress. - /// . - public async Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { progress.Report(0); diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index 7c27ae384..065008157 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -58,13 +58,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks }; } - /// - /// Executes the internal. - /// - /// The cancellation token. - /// The progress. - /// Task. - public Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index dc5eb7391..63f11a22c 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs @@ -8,10 +8,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers /// /// Represents a task trigger that fires everyday. /// - public sealed class DailyTrigger : ITaskTrigger + public sealed class DailyTrigger : ITaskTrigger, IDisposable { private readonly TimeSpan _timeOfDay; private Timer? _timer; + private bool _disposed = false; /// /// Initializes a new instance of the class. @@ -71,6 +72,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers private void DisposeTimer() { _timer?.Dispose(); + _timer = null; } /// @@ -80,5 +82,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers { Triggered?.Invoke(this, EventArgs.Empty); } + + /// + public void Dispose() + { + if (_disposed) + { + return; + } + + DisposeTimer(); + + _disposed = true; + } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs index 927f57e95..3eb800199 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs @@ -9,11 +9,12 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers /// /// Represents a task trigger that runs repeatedly on an interval. /// - public sealed class IntervalTrigger : ITaskTrigger + public sealed class IntervalTrigger : ITaskTrigger, IDisposable { private readonly TimeSpan _interval; private DateTime _lastStartDate; private Timer? _timer; + private bool _disposed = false; /// /// Initializes a new instance of the class. @@ -89,6 +90,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers private void DisposeTimer() { _timer?.Dispose(); + _timer = null; } /// @@ -104,5 +106,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers Triggered(this, EventArgs.Empty); } } + + /// + public void Dispose() + { + if (_disposed) + { + return; + } + + DisposeTimer(); + + _disposed = true; + } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs index 2392b20fd..fab49f2fb 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs @@ -8,11 +8,12 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers /// /// Represents a task trigger that fires on a weekly basis. /// - public sealed class WeeklyTrigger : ITaskTrigger + public sealed class WeeklyTrigger : ITaskTrigger, IDisposable { private readonly TimeSpan _timeOfDay; private readonly DayOfWeek _dayOfWeek; private Timer? _timer; + private bool _disposed = false; /// /// Initializes a new instance of the class. @@ -94,6 +95,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers private void DisposeTimer() { _timer?.Dispose(); + _timer = null; } /// @@ -103,5 +105,18 @@ namespace Emby.Server.Implementations.ScheduledTasks.Triggers { Triggered?.Invoke(this, EventArgs.Empty); } + + /// + public void Dispose() + { + if (_disposed) + { + return; + } + + DisposeTimer(); + + _disposed = true; + } } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 2b0193771..066944c6a 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -138,10 +138,10 @@ namespace MediaBrowser.Controller.Library /// Validate and refresh the People sub-set of the IBN. /// The items are stored in the db but not loaded into memory until actually requested by an operation. /// - /// The cancellation token. /// The progress. + /// The cancellation token. /// Task. - Task ValidatePeople(CancellationToken cancellationToken, IProgress progress); + Task ValidatePeopleAsync(IProgress progress, CancellationToken cancellationToken); /// /// Reloads the root media folder. diff --git a/MediaBrowser.Model/Tasks/IScheduledTask.cs b/MediaBrowser.Model/Tasks/IScheduledTask.cs index bf87088e4..123902d90 100644 --- a/MediaBrowser.Model/Tasks/IScheduledTask.cs +++ b/MediaBrowser.Model/Tasks/IScheduledTask.cs @@ -36,10 +36,10 @@ namespace MediaBrowser.Model.Tasks /// /// Executes the task. /// - /// The cancellation token. /// The progress. + /// The cancellation token. /// Task. - Task Execute(CancellationToken cancellationToken, IProgress progress); + Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken); /// /// Gets the default triggers that define when the task will run. diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 58651d42a..eb9071a52 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -63,7 +63,8 @@ namespace MediaBrowser.Providers.MediaInfo return _config.GetConfiguration("subtitles"); } - public async Task Execute(CancellationToken cancellationToken, IProgress progress) + /// + public async Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var options = GetOptions(); @@ -210,6 +211,7 @@ namespace MediaBrowser.Providers.MediaInfo return true; } + /// public IEnumerable GetDefaultTriggers() { return new[] diff --git a/jellyfin.ruleset b/jellyfin.ruleset index cc7c54b97..1c834de82 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -57,6 +57,10 @@ + + + + @@ -80,6 +84,8 @@ + + diff --git a/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs b/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs index 03acc6911..d80925fc9 100644 --- a/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs +++ b/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs @@ -51,7 +51,7 @@ public class KeyframeExtractionScheduledTask : IScheduledTask public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory"); /// - public Task Execute(CancellationToken cancellationToken, IProgress progress) + public Task ExecuteAsync(IProgress progress, CancellationToken cancellationToken) { var query = new InternalItemsQuery {