diff --git a/MPF.Library/Utilities/DumpEnvironment.cs b/MPF.Library/Utilities/DumpEnvironment.cs
index ba70d826..ba6e892a 100644
--- a/MPF.Library/Utilities/DumpEnvironment.cs
+++ b/MPF.Library/Utilities/DumpEnvironment.cs
@@ -74,7 +74,7 @@ namespace MPF.Utilities
///
/// Queue of items that need to be logged
///
- private readonly ConcurrentQueue outputQueue = new ConcurrentQueue();
+ private ProcessingQueue outputQueue;
///
/// Event handler for data returned from a process
@@ -87,20 +87,9 @@ namespace MPF.Utilities
///
/// Process the outputs in the queue
///
- private void ProcessOutputs()
+ private void ProcessOutputs(string nextOutput)
{
- while (true)
- {
- // Nothing in the queue means we get to idle
- if (outputQueue.Count == 0)
- continue;
-
- // Get the next item from the queue
- if (!outputQueue.TryDequeue(out string nextOutput))
- continue;
-
- ReportStatus.Invoke(this, nextOutput);
- }
+ ReportStatus.Invoke(this, nextOutput);
}
#endregion
@@ -396,7 +385,7 @@ namespace MPF.Utilities
// Invoke output processing, if needed
if (!Options.ToolsInSeparateWindow)
{
- Task.Run(() => ProcessOutputs());
+ outputQueue = new ProcessingQueue(ProcessOutputs);
Parameters.ReportStatus += OutputToLog;
}
@@ -411,9 +400,12 @@ namespace MPF.Utilities
result = await Task.Run(() => ExecuteAdditionalTools());
progress?.Report(result);
- // Remove evet habdler if needed
+ // Remove event handler if needed
if (!Options.ToolsInSeparateWindow)
+ {
+ outputQueue.Dispose();
Parameters.ReportStatus -= OutputToLog;
+ }
return result;
}
diff --git a/MPF.Library/Utilities/ProcessingQueue.cs b/MPF.Library/Utilities/ProcessingQueue.cs
index 83edca3b..bfbcf92d 100644
--- a/MPF.Library/Utilities/ProcessingQueue.cs
+++ b/MPF.Library/Utilities/ProcessingQueue.cs
@@ -4,7 +4,7 @@ using System.Threading.Tasks;
namespace MPF.Utilities
{
- internal class ProcessingQueue
+ public class ProcessingQueue : IDisposable
{
///
/// Internal queue to hold data to process
@@ -16,11 +16,33 @@ namespace MPF.Utilities
///
private readonly Action CustomProcessing;
+ ///
+ /// Internal processing task for dequeueing
+ ///
+ private readonly Task ProcessingTask;
+
public ProcessingQueue(Action customProcessing)
{
this.InternalQueue = new ConcurrentQueue();
this.CustomProcessing = customProcessing;
- Task.Run(() => ProcessQueue());
+ this.ProcessingTask = Task.Run(() => ProcessQueue());
+ }
+
+ ///
+ /// Dispose the current instance
+ ///
+ public void Dispose()
+ {
+ this.ProcessingTask.Dispose();
+ }
+
+ ///
+ /// Enqueue a new item for processing
+ ///
+ ///
+ public void Enqueue(T item)
+ {
+ this.InternalQueue.Enqueue(item);
}
///
diff --git a/MPF/UserControls/LogOutput.xaml.cs b/MPF/UserControls/LogOutput.xaml.cs
index a79689f8..67114f2a 100644
--- a/MPF/UserControls/LogOutput.xaml.cs
+++ b/MPF/UserControls/LogOutput.xaml.cs
@@ -1,14 +1,13 @@
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
+using MPF.Utilities;
namespace MPF.UserControls
{
@@ -27,7 +26,7 @@ namespace MPF.UserControls
///
/// Queue of items that need to be logged
///
- private readonly ConcurrentQueue logQueue;
+ private readonly ProcessingQueue logQueue;
///
/// List of Matchers for progress tracking
@@ -58,8 +57,7 @@ namespace MPF.UserControls
AddAaruMatchers();
AddDiscImageCreatorMatchers();
- logQueue = new ConcurrentQueue();
- Task.Run(() => ProcessLogLines());
+ logQueue = new ProcessingQueue(ProcessLogLine);
}
#region Matching
@@ -370,77 +368,67 @@ namespace MPF.UserControls
///
/// Process the log lines in the queue
///
- private void ProcessLogLines()
+ /// LogLine item to process
+ private void ProcessLogLine(LogLine nextLogLine)
{
- while (true)
+ // Null text gets ignored
+ string nextText = Dispatcher.Invoke(() => nextLogLine.Text);
+ if (nextText == null)
+ return;
+
+ try
{
- // Nothing in the queue means we get to idle
- if (logQueue.Count == 0)
- continue;
+ // Get last line
+ lastLine = lastLine ?? GetLastLine();
- // Get the next item from the queue
- if (!logQueue.TryDequeue(out LogLine nextLogLine))
- continue;
-
- // Null text gets ignored
- string nextText = Dispatcher.Invoke(() => nextLogLine.Text);
- if (nextText == null)
- continue;
-
- try
+ // Always append if there's no previous line
+ if (lastLine == null)
{
- // Get last line
- lastLine = lastLine ?? GetLastLine();
+ AppendToTextBox(nextLogLine);
+ lastUsedMatcher = _matchers.FirstOrDefault(m => m?.Matches(nextText) == true);
+ }
+ // Return always means overwrite
+ else if (nextText.StartsWith("\r"))
+ {
+ ReplaceLastLine(nextLogLine);
+ }
+ // If we have a cached matcher and we match
+ else if (lastUsedMatcher?.Matches(nextText) == true)
+ {
+ ReplaceLastLine(nextLogLine);
+ }
+ else
+ {
+ // Get the first matching Matcher
+ var firstMatcher = _matchers.FirstOrDefault(m => m?.Matches(nextText) == true);
+ if (firstMatcher.HasValue)
+ {
+ string lastText = Dispatcher.Invoke(() => { return lastLine.Text; });
+ if (firstMatcher.Value.Matches(lastText))
+ ReplaceLastLine(nextLogLine);
+ else if (string.IsNullOrWhiteSpace(lastText))
+ ReplaceLastLine(nextLogLine);
+ else
+ AppendToTextBox(nextLogLine);
- // Always append if there's no previous line
- if (lastLine == null)
- {
- AppendToTextBox(nextLogLine);
- lastUsedMatcher = _matchers.FirstOrDefault(m => m?.Matches(nextText) == true);
- }
- // Return always means overwrite
- else if (nextText.StartsWith("\r"))
- {
- ReplaceLastLine(nextLogLine);
- }
- // If we have a cached matcher and we match
- else if (lastUsedMatcher?.Matches(nextText) == true)
- {
- ReplaceLastLine(nextLogLine);
+ // Cache the last used Matcher
+ lastUsedMatcher = firstMatcher;
}
+ // Default case for all other text
else
{
- // Get the first matching Matcher
- var firstMatcher = _matchers.FirstOrDefault(m => m?.Matches(nextText) == true);
- if (firstMatcher.HasValue)
- {
- string lastText = Dispatcher.Invoke(() => { return lastLine.Text; });
- if (firstMatcher.Value.Matches(lastText))
- ReplaceLastLine(nextLogLine);
- else if (string.IsNullOrWhiteSpace(lastText))
- ReplaceLastLine(nextLogLine);
- else
- AppendToTextBox(nextLogLine);
-
- // Cache the last used Matcher
- lastUsedMatcher = firstMatcher;
- }
- // Default case for all other text
- else
- {
- AppendToTextBox(nextLogLine);
- lastUsedMatcher = null;
- }
+ AppendToTextBox(nextLogLine);
+ lastUsedMatcher = null;
}
+ }
- // Update the bar if needed
- ProcessStringForProgressBar(nextText, lastUsedMatcher);
- }
- catch (Exception ex)
- {
- // In the event that something fails horribly, we want to log
- AppendToTextBox(new LogLine(ex.ToString(), LogLevel.ERROR));
- }
+ // Update the bar if needed
+ ProcessStringForProgressBar(nextText, lastUsedMatcher);
+ }
+ catch (Exception ex)
+ {
+ // In the event that something fails horribly, we want to log
+ AppendToTextBox(new LogLine(ex.ToString(), LogLevel.ERROR));
}
}