Skip to content

Commit 5ee7382

Browse files
committed
re-enable log-to-file
1 parent f38e7cc commit 5ee7382

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

Gui/Models/ObjectEditorModel.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using SixLabors.ImageSharp;
1111
using SixLabors.ImageSharp.PixelFormats;
1212
using System;
13+
using System.Collections.Concurrent;
1314
using System.Collections.Generic;
1415
using System.Collections.ObjectModel;
1516
using System.IO;
@@ -20,7 +21,7 @@
2021

2122
namespace OpenLoco.Gui.Models
2223
{
23-
public class ObjectEditorModel
24+
public class ObjectEditorModel : IDisposable
2425
{
2526
public EditorSettings Settings { get; private set; }
2627

@@ -58,11 +59,15 @@ public class ObjectEditorModel
5859

5960
public HttpClient? WebClient { get; }
6061

62+
readonly ConcurrentQueue<string> logQueue = new();
63+
readonly SemaphoreSlim logFileLock = new(1, 1); // Allow only 1 concurrent write
64+
6165
public ObjectEditorModel()
6266
{
6367
Logger = new Logger();
6468
LoggerObservableLogs = [];
6569
Logger.LogAdded += (sender, laea) => Dispatcher.UIThread.Post(() => LoggerObservableLogs.Insert(0, laea.Log));
70+
Logger.LogAdded += (sender, laea) => LogAsync(laea.Log.ToString()).ConfigureAwait(false);
6671

6772
LoadSettings();
6873
InitialiseDownloadDirectory();
@@ -80,6 +85,43 @@ public ObjectEditorModel()
8085
}
8186
}
8287

88+
public async Task LogAsync(string message)
89+
{
90+
logQueue.Enqueue(message);
91+
await WriteLogsToFileAsync(); // Start the async writing process
92+
}
93+
94+
async Task WriteLogsToFileAsync()
95+
{
96+
if (logQueue.IsEmpty)
97+
{
98+
return; // Nothing to write
99+
}
100+
101+
if (await logFileLock.WaitAsync(0)) // Non-blocking wait if available.
102+
{
103+
try
104+
{
105+
while (logQueue.TryDequeue(out var logMessage))
106+
{
107+
try
108+
{
109+
await File.AppendAllTextAsync(LoggingFile, logMessage + Environment.NewLine);
110+
}
111+
catch (Exception ex)
112+
{
113+
Console.WriteLine($"Error writing to log file: {ex.Message}");
114+
// Consider logging to a separate error file or using a more robust logging framework
115+
}
116+
}
117+
}
118+
finally
119+
{
120+
_ = logFileLock.Release(); // Release the semaphore
121+
}
122+
}
123+
}
124+
83125
void LoadSettings()
84126
{
85127
Settings = EditorSettings.Load(SettingsFile, Logger);
@@ -430,5 +472,34 @@ public async Task UploadDatToServer(ObjectIndexEntry dat)
430472
await Client.UploadDatFileAsync(WebClient, dat.Filename, await File.ReadAllBytesAsync(filename), lastModifiedTime, Logger);
431473
await Task.Delay(100); // wait 100ms, ie don't DoS the server
432474
}
475+
476+
public async Task CloseAsync()
477+
{
478+
// Wait for any pending writes to complete.
479+
await logFileLock.WaitAsync(); // Acquire the semaphore
480+
_ = logFileLock.Release(); // Release it immediately after. This is just to wait.
481+
482+
// Process any remaining logs in the queue.
483+
await WriteLogsToFileAsync(); // One last flush.
484+
485+
logFileLock.Dispose(); // Dispose of the semaphore
486+
}
487+
488+
public void Dispose()
489+
{
490+
Dispose(true);
491+
GC.SuppressFinalize(this); // Important for proper disposal
492+
}
493+
494+
protected virtual void Dispose(bool disposing)
495+
{
496+
if (disposing)
497+
{
498+
// Wait for logging to complete synchronously.
499+
Task.Run(CloseAsync).Wait(); // <--- Key change
500+
logFileLock?.Dispose(); // Dispose of the semaphore
501+
}
502+
}
503+
433504
}
434505
}

0 commit comments

Comments
 (0)