summaryrefslogtreecommitdiffstats
path: root/win/CS/HandBrakeWPF/Services
diff options
context:
space:
mode:
authorScott <[email protected]>2020-04-29 19:06:11 +0100
committerGitHub <[email protected]>2020-04-29 19:06:11 +0100
commit91051b41df7f9e6da68d14c9e806968df61ef050 (patch)
tree90293ad067e14e9eff409ed7bf5d105df3697a45 /win/CS/HandBrakeWPF/Services
parent565dae9f71330b87c5e7898a469052446c4592f0 (diff)
WinGui: Enable multi-instance support. (#2797)
Diffstat (limited to 'win/CS/HandBrakeWPF/Services')
-rw-r--r--win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs26
-rw-r--r--win/CS/HandBrakeWPF/Services/Logging/LogInstanceManager.cs64
-rw-r--r--win/CS/HandBrakeWPF/Services/Queue/Interfaces/IQueueService.cs5
-rw-r--r--win/CS/HandBrakeWPF/Services/Queue/QueueService.cs65
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));
+ }
}
}