Apply code-quality fixes to Plugin.cs IAsyncDalamudPlugin refactor
I-1: rewrite property-shape comment to reflect that all properties (not
just Phase-2 ones) moved to { get; private set; } = null!;.
I-3: drop plan-jargon (Q1=A / Q3=B / Task 5) from source comments;
replace with durable rationale and a version-anchored TODO for the
FontManager.BuildFontsAsync follow-up.
I-4: remove German-word leak ("pflicht") from English comment in
DisposeAsync.
M-5: wrap each cleanup line inside Framework.RunOnFrameworkThread with
CaptureFailure so a single Dispose throw no longer strands subsequent
cleanup. Drops the inline try/swallow on SetChatInteractable. Mirrors
Lightless DisposeFrameworkBoundServicesAsync pattern.
This commit is contained in:
+29
-23
@@ -49,9 +49,10 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
|
|
||||||
public readonly WindowSystem WindowSystem = new(PluginName);
|
public readonly WindowSystem WindowSystem = new(PluginName);
|
||||||
|
|
||||||
// v1.4.3: Phase-2 services need private setters now that LoadAsync
|
// v1.4.3: properties moved from { get; } to { get; private set; } = null!;
|
||||||
// owns their construction. Phase-1-only services (Commands, Functions,
|
// because LoadAsync now owns construction of the Phase-2 services.
|
||||||
// Ipc, ExtraChat, TypingIpc) keep their setters for symmetry.
|
// Phase-1 services use the same shape for consistency, even though
|
||||||
|
// they're still allocated in the ctor.
|
||||||
public SettingsWindow SettingsWindow { get; private set; } = null!;
|
public SettingsWindow SettingsWindow { get; private set; } = null!;
|
||||||
public ChatLogWindow ChatLogWindow { get; private set; } = null!;
|
public ChatLogWindow ChatLogWindow { get; private set; } = null!;
|
||||||
public DbViewer DbViewer { get; private set; } = null!;
|
public DbViewer DbViewer { get; private set; } = null!;
|
||||||
@@ -486,14 +487,13 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Group A: Font + Theme parallel (Q1=A). Both are CPU-bound,
|
// Group A: Font + Theme parallel — both CPU-bound, independent, and
|
||||||
// independent, and dominate the load-time profile. Everything
|
// dominate the load-time profile. Everything else stays sequential to
|
||||||
// else stays sequential to keep ordering simple.
|
// keep ordering simple.
|
||||||
// Q3=B transition: BuildFonts() is sync today; Task 5 converts
|
|
||||||
// FontManager itself to BuildFontsAsync.
|
|
||||||
var fontTask = Task.Run(() =>
|
var fontTask = Task.Run(() =>
|
||||||
{
|
{
|
||||||
FontManager = new FontManager();
|
FontManager = new FontManager();
|
||||||
|
// TODO(v1.4.x): replace with FontManager.BuildFontsAsync(cancellationToken)
|
||||||
FontManager.BuildFonts();
|
FontManager.BuildFonts();
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
|
||||||
@@ -620,7 +620,7 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Auto-Tell-Tabs unsubscribes from MessageProcessed before MessageManager
|
// Auto-Tell-Tabs unsubscribes from MessageProcessed before MessageManager
|
||||||
// goes away. Pure-memory cleanup, no framework-thread pflicht.
|
// goes away. Pure-memory cleanup, no framework-thread requirement.
|
||||||
failure = CaptureFailure(failure, () => AutoTellTabsService?.Dispose());
|
failure = CaptureFailure(failure, () => AutoTellTabsService?.Dispose());
|
||||||
|
|
||||||
// v1.4.0 F6.2 — MessageManager has its own async dispose path
|
// v1.4.0 F6.2 — MessageManager has its own async dispose path
|
||||||
@@ -636,35 +636,41 @@ public sealed class Plugin : IAsyncDalamudPlugin
|
|||||||
// framework thread. WindowSystem mutations and IPC subscriber
|
// framework thread. WindowSystem mutations and IPC subscriber
|
||||||
// disposes touch Dalamud state that's only safe from the framework.
|
// disposes touch Dalamud state that's only safe from the framework.
|
||||||
// Worker-thread DisposeAsync would race the next Draw tick.
|
// Worker-thread DisposeAsync would race the next Draw tick.
|
||||||
failure = await CaptureFailureAsync(failure, async () =>
|
// Per-line CaptureFailure so a single throw can't strand the lines
|
||||||
|
// behind it; mirrors Lightless DisposeFrameworkBoundServicesAsync.
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await Framework.RunOnFrameworkThread(() =>
|
await Framework.RunOnFrameworkThread(() =>
|
||||||
{
|
{
|
||||||
// Game-Functions first — other services may still query
|
// Game-Functions first — other services may still query
|
||||||
// chat-interactable state during their Dispose.
|
// chat-interactable state during their Dispose.
|
||||||
try { GameFunctions.GameFunctions.SetChatInteractable(true); } catch { /* swallowed */ }
|
failure = CaptureFailure(failure, () => GameFunctions.GameFunctions.SetChatInteractable(true));
|
||||||
|
|
||||||
// IPC subscribers — dispose before windows so any final
|
// IPC subscribers — dispose before windows so any final
|
||||||
// event firing from the IPC source can't reach a half-torn
|
// event firing from the IPC source can't reach a half-torn
|
||||||
// ChatLogWindow.
|
// ChatLogWindow.
|
||||||
HonorificService?.Dispose();
|
failure = CaptureFailure(failure, () => HonorificService?.Dispose());
|
||||||
TypingIpc?.Dispose();
|
failure = CaptureFailure(failure, () => TypingIpc?.Dispose());
|
||||||
ExtraChat?.Dispose();
|
failure = CaptureFailure(failure, () => ExtraChat?.Dispose());
|
||||||
Ipc?.Dispose();
|
failure = CaptureFailure(failure, () => Ipc?.Dispose());
|
||||||
|
|
||||||
// Windows — RemoveAllWindows first, then per-window Dispose.
|
// Windows — RemoveAllWindows first, then per-window Dispose.
|
||||||
// Order matches the pre-v1.4.3 Dispose body byte-for-byte.
|
// Order matches the pre-v1.4.3 Dispose body byte-for-byte.
|
||||||
// CommandHelpWindow and FirstRunWizard don't implement
|
// CommandHelpWindow and FirstRunWizard don't implement
|
||||||
// IDisposable; their resources are reclaimed via WindowSystem.
|
// IDisposable; their resources are reclaimed via WindowSystem.
|
||||||
WindowSystem?.RemoveAllWindows();
|
failure = CaptureFailure(failure, () => WindowSystem?.RemoveAllWindows());
|
||||||
ChatLogWindow?.Dispose();
|
failure = CaptureFailure(failure, () => ChatLogWindow?.Dispose());
|
||||||
DbViewer?.Dispose();
|
failure = CaptureFailure(failure, () => DbViewer?.Dispose());
|
||||||
InputPreview?.Dispose();
|
failure = CaptureFailure(failure, () => InputPreview?.Dispose());
|
||||||
SettingsWindow?.Dispose();
|
failure = CaptureFailure(failure, () => SettingsWindow?.Dispose());
|
||||||
DebuggerWindow?.Dispose();
|
failure = CaptureFailure(failure, () => DebuggerWindow?.Dispose());
|
||||||
SeStringDebugger?.Dispose();
|
failure = CaptureFailure(failure, () => SeStringDebugger?.Dispose());
|
||||||
}).ConfigureAwait(false);
|
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
failure ??= ex;
|
||||||
|
}
|
||||||
|
|
||||||
// Pure-memory cleanups — no Framework / UI / IPC touch, so they
|
// Pure-memory cleanups — no Framework / UI / IPC touch, so they
|
||||||
// run on whatever thread DisposeAsync resumes on.
|
// run on whatever thread DisposeAsync resumes on.
|
||||||
|
|||||||
Reference in New Issue
Block a user