diff options
Diffstat (limited to 'win/CS/HandBrakeWPF/Services')
4 files changed, 104 insertions, 56 deletions
diff --git a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs index e6d8cb7c0..fdd2a01e5 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs @@ -40,6 +40,7 @@ namespace HandBrakeWPF.Services.Encode private readonly IUserSettingService userSettingService; private readonly ILogInstanceManager logInstanceManager; private readonly IHbFunctionsProvider hbFunctionsProvider; + private readonly object portLock = new object(); private IEncodeInstance instance; private DateTime startTime; private EncodeTask currentTask; @@ -107,19 +108,24 @@ namespace HandBrakeWPF.Services.Encode } int verbosity = this.userSettingService.GetUserSetting<int>(UserSettingConstants.Verbosity); - this.instance = task.IsPreviewEncode ? HandBrakeInstanceManager.GetPreviewInstance(verbosity, this.userSettingService) : HandBrakeInstanceManager.GetEncodeInstance(verbosity, configuration, this.encodeLogService, userSettingService); - - this.instance.EncodeCompleted += this.InstanceEncodeCompleted; - this.instance.EncodeProgress += this.InstanceEncodeProgress; - this.IsEncoding = true; - this.isPreviewInstance = task.IsPreviewEncode; + // Prevent port stealing if multiple jobs start at the same time. + lock (portLock) + { + this.instance = task.IsPreviewEncode ? HandBrakeInstanceManager.GetPreviewInstance(verbosity, this.userSettingService) : HandBrakeInstanceManager.GetEncodeInstance(verbosity, configuration, this.encodeLogService, userSettingService); + + this.instance.EncodeCompleted += this.InstanceEncodeCompleted; + this.instance.EncodeProgress += this.InstanceEncodeProgress; - // Verify the Destination Path Exists, and if not, create it. - this.VerifyEncodeDestinationPath(task); + this.IsEncoding = true; + this.isPreviewInstance = task.IsPreviewEncode; - // Get an EncodeJob object for the Interop Library - this.instance.StartEncode(EncodeTaskFactory.Create(task, configuration, hbFunctionsProvider.GetHbFunctionsWrapper())); + // Verify the Destination Path Exists, and if not, create it. + this.VerifyEncodeDestinationPath(task); + + // Get an EncodeJob object for the Interop Library + this.instance.StartEncode(EncodeTaskFactory.Create(task, configuration, hbFunctionsProvider.GetHbFunctionsWrapper())); + } // Fire the Encode Started Event this.InvokeEncodeStarted(System.EventArgs.Empty); diff --git a/win/CS/HandBrakeWPF/Services/Logging/LogInstanceManager.cs b/win/CS/HandBrakeWPF/Services/Logging/LogInstanceManager.cs index 4e1290024..16c9aa7dc 100644 --- a/win/CS/HandBrakeWPF/Services/Logging/LogInstanceManager.cs +++ b/win/CS/HandBrakeWPF/Services/Logging/LogInstanceManager.cs @@ -19,13 +19,26 @@ namespace HandBrakeWPF.Services.Logging public class LogInstanceManager : ILogInstanceManager { - private Dictionary<string, ILog> logInstances = new Dictionary<string, ILog>(); + private readonly IUserSettingService userSettingService; + private readonly object instanceLock = new object(); + private Dictionary<string, ILog> logInstances = new Dictionary<string, ILog>(); + private int maxInstances; public LogInstanceManager(IUserSettingService userSettingService) { - this.maxInstances = userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes); + this.userSettingService = userSettingService; + this.maxInstances = this.userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes); + userSettingService.SettingChanged += this.UserSettingService_SettingChanged; + } + + private void UserSettingService_SettingChanged(object sender, HandBrakeWPF.EventArgs.SettingChangedEventArgs e) + { + if (e.Key == UserSettingConstants.SimultaneousEncodes) + { + this.maxInstances = this.userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes); + } } public event EventHandler NewLogInstanceRegistered; @@ -36,19 +49,22 @@ namespace HandBrakeWPF.Services.Logging public void RegisterLoggerInstance(string filename, ILog log, bool isMaster) { - if (string.IsNullOrEmpty(this.ApplicationAndScanLog)) + lock (this.instanceLock) { - // The application startup sets the initial log file. - this.ApplicationAndScanLog = filename; - } + if (string.IsNullOrEmpty(this.ApplicationAndScanLog)) + { + // The application startup sets the initial log file. + this.ApplicationAndScanLog = filename; + } - this.logInstances.Add(filename, log); + this.logInstances.Add(filename, log); - this.CleanupInstance(); + this.CleanupInstance(); - if (isMaster) - { - this.MasterLogInstance = log; + if (isMaster) + { + this.MasterLogInstance = log; + } } this.OnNewLogInstanceRegistered(); @@ -56,20 +72,26 @@ namespace HandBrakeWPF.Services.Logging public List<string> GetLogFiles() { - return this.logInstances.Keys.ToList(); + lock (this.instanceLock) + { + return this.logInstances.Keys.ToList(); + } } public ILog GetLogInstance(string filename) { - if (string.IsNullOrEmpty(filename)) + lock (this.instanceLock) { - return null; - } - - ILog logger; - if (this.logInstances.TryGetValue(filename, out logger)) - { - return logger; + if (string.IsNullOrEmpty(filename)) + { + return null; + } + + ILog logger; + if (this.logInstances.TryGetValue(filename, out logger)) + { + return logger; + } } return null; @@ -87,7 +109,7 @@ namespace HandBrakeWPF.Services.Logging if (encodeLogs.Count > this.maxInstances) { this.logInstances.Remove(removalKey); - } + } } } } diff --git a/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueService.cs b/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueService.cs index 1a2a04cce..5bf759917 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueService.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueService.cs @@ -63,6 +63,11 @@ namespace HandBrakeWPF.Services.Queue.Interfaces int ErrorCount { get; } /// <summary> + /// Gets the number of completed jobs. + /// </summary> + int CompletedCount { get; } + + /// <summary> /// Gets a value indicating whether IsProcessing. /// </summary> bool IsProcessing { get; } diff --git a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs index 6cbf709e5..41cba661f 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs @@ -59,9 +59,12 @@ namespace HandBrakeWPF.Services.Queue private readonly ObservableCollection<QueueTask> queue = new ObservableCollection<QueueTask>(); private readonly string queueFile; + private readonly object queueFileLock = new object(); + private bool clearCompleted; private int allowedInstances; private int jobIdCounter = 0; + private bool processIsolationEnabled; public QueueService(IUserSettingService userSettingService, ILog logService, IErrorService errorService, ILogInstanceManager logInstanceManager, IHbFunctionsProvider hbFunctionsProvider) { @@ -75,6 +78,7 @@ namespace HandBrakeWPF.Services.Queue this.queueFile = string.Format("{0}{1}.json", QueueRecoveryHelper.QueueFileName, GeneralUtilities.ProcessId); this.allowedInstances = this.userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes); + this.processIsolationEnabled = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ProcessIsolationEnabled); } public event EventHandler<QueueProgressEventArgs> JobProcessingStarted; @@ -105,6 +109,8 @@ namespace HandBrakeWPF.Services.Queue } } + public int CompletedCount => this.queue.Count(item => item.Status == QueueItemStatus.Completed); + public bool IsPaused { get; private set; } public bool IsProcessing { get; private set; } @@ -130,33 +136,31 @@ namespace HandBrakeWPF.Services.Queue public void BackupQueue(string exportPath) { - Stopwatch watch = Stopwatch.StartNew(); - - string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly()); - string tempPath = !string.IsNullOrEmpty(exportPath) - ? exportPath - : Path.Combine(appDataPath, string.Format(this.queueFile, string.Empty)); - - // Make a copy of the file before we replace it. This way, if we crash we can recover. - if (File.Exists(tempPath)) + lock (this.queueFileLock) { - File.Copy(tempPath, tempPath + ".last"); - } + string appDataPath = DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly()); + string tempPath = !string.IsNullOrEmpty(exportPath) + ? exportPath + : Path.Combine(appDataPath, string.Format(this.queueFile, string.Empty)); - using (StreamWriter writer = new StreamWriter(tempPath)) - { - List<QueueTask> tasks = this.queue.Where(item => item.Status != QueueItemStatus.Completed).ToList(); - string queueJson = JsonConvert.SerializeObject(tasks, Formatting.Indented); - writer.Write(queueJson); - } + // Make a copy of the file before we replace it. This way, if we crash we can recover. + if (File.Exists(tempPath)) + { + File.Copy(tempPath, tempPath + ".last"); + } - if (File.Exists(tempPath + ".last")) - { - File.Delete(tempPath + ".last"); - } + using (StreamWriter writer = new StreamWriter(tempPath)) + { + List<QueueTask> tasks = this.queue.Where(item => item.Status != QueueItemStatus.Completed).ToList(); + string queueJson = JsonConvert.SerializeObject(tasks, Formatting.Indented); + writer.Write(queueJson); + } - watch.Stop(); - Debug.WriteLine("Queue Save (ms): " + watch.ElapsedMilliseconds); + if (File.Exists(tempPath + ".last")) + { + File.Delete(tempPath + ".last"); + } + } } public void ExportCliJson(string exportPath) @@ -447,6 +451,9 @@ namespace HandBrakeWPF.Services.Queue this.IsPaused = false; this.clearCompleted = isClearCompleted; + this.allowedInstances = this.userSettingService.GetUserSetting<int>(UserSettingConstants.SimultaneousEncodes); + this.processIsolationEnabled = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ProcessIsolationEnabled); + // Unpause all active jobs. foreach (ActiveJob job in this.activeJobs) { @@ -523,6 +530,11 @@ namespace HandBrakeWPF.Services.Queue private void ProcessNextJob() { + if (!this.processIsolationEnabled) + { + this.allowedInstances = 1; + } + if (this.activeJobs.Count >= this.allowedInstances) { return; @@ -555,8 +567,11 @@ namespace HandBrakeWPF.Services.Queue { this.BackupQueue(string.Empty); - // Fire the event to tell connected services. - this.InvokeQueueCompleted(new QueueCompletedEventArgs(false)); + if (!this.activeJobs.Any(a => a.IsEncoding)) + { + // Fire the event to tell connected services. + this.InvokeQueueCompleted(new QueueCompletedEventArgs(false)); + } } } |