mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
Fix and use ProcessingQueue
This commit is contained in:
@@ -74,7 +74,7 @@ namespace MPF.Utilities
|
||||
/// <summary>
|
||||
/// Queue of items that need to be logged
|
||||
/// </summary>
|
||||
private readonly ConcurrentQueue<string> outputQueue = new ConcurrentQueue<string>();
|
||||
private ProcessingQueue<string> outputQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Event handler for data returned from a process
|
||||
@@ -87,20 +87,9 @@ namespace MPF.Utilities
|
||||
/// <summary>
|
||||
/// Process the outputs in the queue
|
||||
/// </summary>
|
||||
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<string>(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;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace MPF.Utilities
|
||||
{
|
||||
internal class ProcessingQueue<T>
|
||||
public class ProcessingQueue<T> : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal queue to hold data to process
|
||||
@@ -16,11 +16,33 @@ namespace MPF.Utilities
|
||||
/// </summary>
|
||||
private readonly Action<T> CustomProcessing;
|
||||
|
||||
/// <summary>
|
||||
/// Internal processing task for dequeueing
|
||||
/// </summary>
|
||||
private readonly Task ProcessingTask;
|
||||
|
||||
public ProcessingQueue(Action<T> customProcessing)
|
||||
{
|
||||
this.InternalQueue = new ConcurrentQueue<T>();
|
||||
this.CustomProcessing = customProcessing;
|
||||
Task.Run(() => ProcessQueue());
|
||||
this.ProcessingTask = Task.Run(() => ProcessQueue());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose the current instance
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.ProcessingTask.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enqueue a new item for processing
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
this.InternalQueue.Enqueue(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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
|
||||
/// <summary>
|
||||
/// Queue of items that need to be logged
|
||||
/// </summary>
|
||||
private readonly ConcurrentQueue<LogLine> logQueue;
|
||||
private readonly ProcessingQueue<LogLine> logQueue;
|
||||
|
||||
/// <summary>
|
||||
/// List of Matchers for progress tracking
|
||||
@@ -58,8 +57,7 @@ namespace MPF.UserControls
|
||||
AddAaruMatchers();
|
||||
AddDiscImageCreatorMatchers();
|
||||
|
||||
logQueue = new ConcurrentQueue<LogLine>();
|
||||
Task.Run(() => ProcessLogLines());
|
||||
logQueue = new ProcessingQueue<LogLine>(ProcessLogLine);
|
||||
}
|
||||
|
||||
#region Matching
|
||||
@@ -370,77 +368,67 @@ namespace MPF.UserControls
|
||||
/// <summary>
|
||||
/// Process the log lines in the queue
|
||||
/// </summary>
|
||||
private void ProcessLogLines()
|
||||
/// <param name="nextLogLine">LogLine item to process</param>
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user