mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
Merge pull request #994 from rootdarkarchon/master
This commit is contained in:
commit
546039fa11
8 changed files with 165 additions and 99 deletions
|
|
@ -9,6 +9,7 @@ using Dalamud.Game.Network.Internal;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
|
@ -145,7 +146,7 @@ namespace Dalamud.Game.ClientState
|
||||||
private IntPtr SetupTerritoryTypeDetour(IntPtr manager, ushort terriType)
|
private IntPtr SetupTerritoryTypeDetour(IntPtr manager, ushort terriType)
|
||||||
{
|
{
|
||||||
this.TerritoryType = terriType;
|
this.TerritoryType = terriType;
|
||||||
this.TerritoryChanged?.Invoke(this, terriType);
|
this.TerritoryChanged?.InvokeSafely(this, terriType);
|
||||||
|
|
||||||
Log.Debug("TerritoryType changed: {0}", terriType);
|
Log.Debug("TerritoryType changed: {0}", terriType);
|
||||||
|
|
||||||
|
|
@ -154,7 +155,7 @@ namespace Dalamud.Game.ClientState
|
||||||
|
|
||||||
private void NetworkHandlersOnCfPop(object sender, Lumina.Excel.GeneratedSheets.ContentFinderCondition e)
|
private void NetworkHandlersOnCfPop(object sender, Lumina.Excel.GeneratedSheets.ContentFinderCondition e)
|
||||||
{
|
{
|
||||||
this.CfPop?.Invoke(this, e);
|
this.CfPop?.InvokeSafely(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FrameworkOnOnUpdateEvent(Framework framework1)
|
private void FrameworkOnOnUpdateEvent(Framework framework1)
|
||||||
|
|
@ -171,7 +172,7 @@ namespace Dalamud.Game.ClientState
|
||||||
Log.Debug("Is login");
|
Log.Debug("Is login");
|
||||||
this.lastConditionNone = false;
|
this.lastConditionNone = false;
|
||||||
this.IsLoggedIn = true;
|
this.IsLoggedIn = true;
|
||||||
this.Login?.Invoke(this, null);
|
this.Login?.InvokeSafely(this, null);
|
||||||
gameGui.ResetUiHideState();
|
gameGui.ResetUiHideState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +181,7 @@ namespace Dalamud.Game.ClientState
|
||||||
Log.Debug("Is logout");
|
Log.Debug("Is logout");
|
||||||
this.lastConditionNone = true;
|
this.lastConditionNone = true;
|
||||||
this.IsLoggedIn = false;
|
this.IsLoggedIn = false;
|
||||||
this.Logout?.Invoke(this, null);
|
this.Logout?.InvokeSafely(this, null);
|
||||||
gameGui.ResetUiHideState();
|
gameGui.ResetUiHideState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,11 +194,11 @@ namespace Dalamud.Game.ClientState
|
||||||
|
|
||||||
if (this.IsPvP)
|
if (this.IsPvP)
|
||||||
{
|
{
|
||||||
this.EnterPvP?.Invoke();
|
this.EnterPvP?.InvokeSafely();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.LeavePvP?.Invoke();
|
this.LeavePvP?.InvokeSafely();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -362,63 +362,64 @@ namespace Dalamud.Game
|
||||||
this.LastUpdate = DateTime.Now;
|
this.LastUpdate = DateTime.Now;
|
||||||
this.LastUpdateUTC = DateTime.UtcNow;
|
this.LastUpdateUTC = DateTime.UtcNow;
|
||||||
|
|
||||||
try
|
this.runOnNextTickTaskList.RemoveAll(x => x.Run());
|
||||||
|
|
||||||
|
if (StatsEnabled && this.Update != null)
|
||||||
{
|
{
|
||||||
this.runOnNextTickTaskList.RemoveAll(x => x.Run());
|
// Stat Tracking for Framework Updates
|
||||||
|
var invokeList = this.Update.GetInvocationList();
|
||||||
|
var notUpdated = StatsHistory.Keys.ToList();
|
||||||
|
|
||||||
if (StatsEnabled && this.Update != null)
|
// Individually invoke OnUpdate handlers and time them.
|
||||||
|
foreach (var d in invokeList)
|
||||||
{
|
{
|
||||||
// Stat Tracking for Framework Updates
|
statsStopwatch.Restart();
|
||||||
var invokeList = this.Update.GetInvocationList();
|
try
|
||||||
var notUpdated = StatsHistory.Keys.ToList();
|
|
||||||
|
|
||||||
// Individually invoke OnUpdate handlers and time them.
|
|
||||||
foreach (var d in invokeList)
|
|
||||||
{
|
{
|
||||||
statsStopwatch.Restart();
|
|
||||||
d.Method.Invoke(d.Target, new object[] { this });
|
d.Method.Invoke(d.Target, new object[] { this });
|
||||||
statsStopwatch.Stop();
|
}
|
||||||
|
catch (Exception ex)
|
||||||
var key = $"{d.Target}::{d.Method.Name}";
|
{
|
||||||
if (notUpdated.Contains(key))
|
Log.Error(ex, "Exception while dispatching Framework::Update event.");
|
||||||
notUpdated.Remove(key);
|
|
||||||
|
|
||||||
if (!StatsHistory.ContainsKey(key))
|
|
||||||
StatsHistory.Add(key, new List<double>());
|
|
||||||
|
|
||||||
StatsHistory[key].Add(statsStopwatch.Elapsed.TotalMilliseconds);
|
|
||||||
|
|
||||||
if (StatsHistory[key].Count > 1000)
|
|
||||||
{
|
|
||||||
StatsHistory[key].RemoveRange(0, StatsHistory[key].Count - 1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup handlers that are no longer being called
|
statsStopwatch.Stop();
|
||||||
foreach (var key in notUpdated)
|
|
||||||
|
var key = $"{d.Target}::{d.Method.Name}";
|
||||||
|
if (notUpdated.Contains(key))
|
||||||
|
notUpdated.Remove(key);
|
||||||
|
|
||||||
|
if (!StatsHistory.ContainsKey(key))
|
||||||
|
StatsHistory.Add(key, new List<double>());
|
||||||
|
|
||||||
|
StatsHistory[key].Add(statsStopwatch.Elapsed.TotalMilliseconds);
|
||||||
|
|
||||||
|
if (StatsHistory[key].Count > 1000)
|
||||||
{
|
{
|
||||||
if (StatsHistory[key].Count > 0)
|
StatsHistory[key].RemoveRange(0, StatsHistory[key].Count - 1000);
|
||||||
{
|
|
||||||
StatsHistory[key].RemoveAt(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StatsHistory.Remove(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// Cleanup handlers that are no longer being called
|
||||||
|
foreach (var key in notUpdated)
|
||||||
{
|
{
|
||||||
this.Update?.Invoke(this);
|
if (StatsHistory[key].Count > 0)
|
||||||
|
{
|
||||||
|
StatsHistory[key].RemoveAt(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StatsHistory.Remove(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
Log.Error(ex, "Exception while dispatching Framework::Update event.");
|
this.Update?.InvokeSafely(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
original:
|
original:
|
||||||
return this.updateHook.OriginalDisposeSafe(framework);
|
return this.updateHook.OriginalDisposeSafe(framework);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,14 +466,7 @@ namespace Dalamud.Game.Gui
|
||||||
var itemId = (ulong)Marshal.ReadInt32(hoverState, 0x138);
|
var itemId = (ulong)Marshal.ReadInt32(hoverState, 0x138);
|
||||||
this.HoveredItem = itemId;
|
this.HoveredItem = itemId;
|
||||||
|
|
||||||
try
|
this.HoveredItemChanged?.InvokeSafely(this, itemId);
|
||||||
{
|
|
||||||
this.HoveredItemChanged?.Invoke(this, itemId);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error(e, "Could not dispatch HoveredItemChanged event.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Verbose("HoverItemId:{0} this:{1}", itemId, hoverState.ToInt64().ToString("X"));
|
Log.Verbose("HoverItemId:{0} this:{1}", itemId, hoverState.ToInt64().ToString("X"));
|
||||||
}
|
}
|
||||||
|
|
@ -515,14 +508,7 @@ namespace Dalamud.Game.Gui
|
||||||
this.HoveredAction.ActionKind = actionKind;
|
this.HoveredAction.ActionKind = actionKind;
|
||||||
this.HoveredAction.BaseActionID = actionId;
|
this.HoveredAction.BaseActionID = actionId;
|
||||||
this.HoveredAction.ActionID = (uint)Marshal.ReadInt32(hoverState, 0x3C);
|
this.HoveredAction.ActionID = (uint)Marshal.ReadInt32(hoverState, 0x3C);
|
||||||
try
|
this.HoveredActionChanged?.InvokeSafely(this, this.HoveredAction);
|
||||||
{
|
|
||||||
this.HoveredActionChanged?.Invoke(this, this.HoveredAction);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Error(e, "Could not dispatch HoveredItemChanged event.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Verbose("HoverActionId: {0}/{1} this:{2}", actionKind, actionId, hoverState.ToInt64().ToString("X"));
|
Log.Verbose("HoverActionId: {0}/{1} this:{2}", actionKind, actionId, hoverState.ToInt64().ToString("X"));
|
||||||
}
|
}
|
||||||
|
|
@ -562,14 +548,7 @@ namespace Dalamud.Game.Gui
|
||||||
// TODO(goat): We should read this from memory directly, instead of relying on catching every toggle.
|
// TODO(goat): We should read this from memory directly, instead of relying on catching every toggle.
|
||||||
this.GameUiHidden = !this.GameUiHidden;
|
this.GameUiHidden = !this.GameUiHidden;
|
||||||
|
|
||||||
try
|
this.UiHideToggled?.InvokeSafely(this, this.GameUiHidden);
|
||||||
{
|
|
||||||
this.UiHideToggled?.Invoke(this, this.GameUiHidden);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, "Error on OnUiHideToggled event dispatch");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Debug("UiHide toggled: {0}", this.GameUiHidden);
|
Log.Debug("UiHide toggled: {0}", this.GameUiHidden);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ namespace Dalamud.Game.Network.Internal
|
||||||
Service<ChatGui>.GetNullable()?.Print($"Duty pop: {cfcName}");
|
Service<ChatGui>.GetNullable()?.Print($"Duty pop: {cfcName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.CfPop?.Invoke(this, cfCondition);
|
this.CfPop?.InvokeSafely(this, cfCondition);
|
||||||
}).ContinueWith((task) => Log.Error(task.Exception, "CfPop.Invoke failed."), TaskContinuationOptions.OnlyOnFaulted);
|
}).ContinueWith((task) => Log.Error(task.Exception, "CfPop.Invoke failed."), TaskContinuationOptions.OnlyOnFaulted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -773,7 +773,7 @@ namespace Dalamud.Interface.Internal
|
||||||
var customFontFirstConfigIndex = ioFonts.ConfigData.Size;
|
var customFontFirstConfigIndex = ioFonts.ConfigData.Size;
|
||||||
|
|
||||||
Log.Verbose("[FONT] Invoke OnBuildFonts");
|
Log.Verbose("[FONT] Invoke OnBuildFonts");
|
||||||
this.BuildFonts?.Invoke();
|
this.BuildFonts?.InvokeSafely();
|
||||||
Log.Verbose("[FONT] OnBuildFonts OK!");
|
Log.Verbose("[FONT] OnBuildFonts OK!");
|
||||||
|
|
||||||
for (int i = customFontFirstConfigIndex, i_ = ioFonts.ConfigData.Size; i < i_; i++)
|
for (int i = customFontFirstConfigIndex, i_ = ioFonts.ConfigData.Size; i < i_; i++)
|
||||||
|
|
@ -881,7 +881,7 @@ namespace Dalamud.Interface.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Verbose("[FONT] Invoke OnAfterBuildFonts");
|
Log.Verbose("[FONT] Invoke OnAfterBuildFonts");
|
||||||
this.AfterBuildFonts?.Invoke();
|
this.AfterBuildFonts?.InvokeSafely();
|
||||||
Log.Verbose("[FONT] OnAfterBuildFonts OK!");
|
Log.Verbose("[FONT] OnAfterBuildFonts OK!");
|
||||||
|
|
||||||
if (ioFonts.Fonts[0].NativePtr != DefaultFont.NativePtr)
|
if (ioFonts.Fonts[0].NativePtr != DefaultFont.NativePtr)
|
||||||
|
|
@ -978,7 +978,7 @@ namespace Dalamud.Interface.Internal
|
||||||
Log.Verbose($"Calling resizebuffers swap@{swapChain.ToInt64():X}{bufferCount} {width} {height} {newFormat} {swapChainFlags}");
|
Log.Verbose($"Calling resizebuffers swap@{swapChain.ToInt64():X}{bufferCount} {width} {height} {newFormat} {swapChainFlags}");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.ResizeBuffers?.Invoke();
|
this.ResizeBuffers?.InvokeSafely();
|
||||||
|
|
||||||
// We have to ensure we're working with the main swapchain,
|
// We have to ensure we're working with the main swapchain,
|
||||||
// as viewports might be resizing as well
|
// as viewports might be resizing as well
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ using Dalamud.Interface.GameFonts;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Interface.Internal;
|
||||||
using Dalamud.Interface.Internal.ManagedAsserts;
|
using Dalamud.Interface.Internal.ManagedAsserts;
|
||||||
using Dalamud.Interface.Internal.Notifications;
|
using Dalamud.Interface.Internal.Notifications;
|
||||||
|
using Dalamud.Utility;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using ImGuiScene;
|
using ImGuiScene;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
@ -392,7 +393,7 @@ namespace Dalamud.Interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void OpenConfig()
|
internal void OpenConfig()
|
||||||
{
|
{
|
||||||
this.OpenConfigUi?.Invoke();
|
this.OpenConfigUi?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -400,7 +401,7 @@ namespace Dalamud.Interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void NotifyHideUi()
|
internal void NotifyHideUi()
|
||||||
{
|
{
|
||||||
this.HideUi?.Invoke();
|
this.HideUi?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -408,7 +409,7 @@ namespace Dalamud.Interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void NotifyShowUi()
|
internal void NotifyShowUi()
|
||||||
{
|
{
|
||||||
this.ShowUi?.Invoke();
|
this.ShowUi?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDraw()
|
private void OnDraw()
|
||||||
|
|
@ -428,7 +429,7 @@ namespace Dalamud.Interface
|
||||||
if (!this.lastFrameUiHideState)
|
if (!this.lastFrameUiHideState)
|
||||||
{
|
{
|
||||||
this.lastFrameUiHideState = true;
|
this.lastFrameUiHideState = true;
|
||||||
this.HideUi?.Invoke();
|
this.HideUi?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -437,7 +438,7 @@ namespace Dalamud.Interface
|
||||||
if (this.lastFrameUiHideState)
|
if (this.lastFrameUiHideState)
|
||||||
{
|
{
|
||||||
this.lastFrameUiHideState = false;
|
this.lastFrameUiHideState = false;
|
||||||
this.ShowUi?.Invoke();
|
this.ShowUi?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.interfaceManager.FontsReady)
|
if (!this.interfaceManager.FontsReady)
|
||||||
|
|
@ -470,7 +471,7 @@ namespace Dalamud.Interface
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.Draw?.Invoke();
|
this.Draw?.InvokeSafely();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -503,17 +504,17 @@ namespace Dalamud.Interface
|
||||||
|
|
||||||
private void OnBuildFonts()
|
private void OnBuildFonts()
|
||||||
{
|
{
|
||||||
this.BuildFonts?.Invoke();
|
this.BuildFonts?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAfterBuildFonts()
|
private void OnAfterBuildFonts()
|
||||||
{
|
{
|
||||||
this.AfterBuildFonts?.Invoke();
|
this.AfterBuildFonts?.InvokeSafely();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResizeBuffers()
|
private void OnResizeBuffers()
|
||||||
{
|
{
|
||||||
this.ResizeBuffers?.Invoke();
|
this.ResizeBuffers?.InvokeSafely();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1263,28 +1263,14 @@ internal partial class PluginManager : IDisposable, IServiceType
|
||||||
{
|
{
|
||||||
this.DetectAvailablePluginUpdates();
|
this.DetectAvailablePluginUpdates();
|
||||||
|
|
||||||
try
|
this.OnAvailablePluginsChanged?.InvokeSafely();
|
||||||
{
|
|
||||||
this.OnAvailablePluginsChanged?.Invoke();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, $"Error notifying {nameof(this.OnAvailablePluginsChanged)}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NotifyInstalledPluginsChanged()
|
private void NotifyInstalledPluginsChanged()
|
||||||
{
|
{
|
||||||
this.DetectAvailablePluginUpdates();
|
this.DetectAvailablePluginUpdates();
|
||||||
|
|
||||||
try
|
this.OnInstalledPluginsChanged?.InvokeSafely();
|
||||||
{
|
|
||||||
this.OnInstalledPluginsChanged?.Invoke();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error(ex, $"Error notifying {nameof(this.OnInstalledPluginsChanged)}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Locs
|
private static class Locs
|
||||||
|
|
|
||||||
98
Dalamud/Utility/EventHandlerExtensions.cs
Normal file
98
Dalamud/Utility/EventHandlerExtensions.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Dalamud.Game;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
using static Dalamud.Game.Framework;
|
||||||
|
|
||||||
|
namespace Dalamud.Utility
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions for Events.
|
||||||
|
/// </summary>
|
||||||
|
internal static class EventHandlerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Replacement for Invoke() on EventHandlers to catch exceptions that stop event propagation in case
|
||||||
|
/// of a thrown Exception inside of an invocation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eh">The EventHandler in question.</param>
|
||||||
|
/// <param name="sender">Default sender for Invoke equivalent.</param>
|
||||||
|
/// <param name="e">Default EventArgs for Invoke equivalent.</param>
|
||||||
|
public static void InvokeSafely(this EventHandler eh, object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (eh == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var handler in eh.GetInvocationList().Cast<EventHandler>())
|
||||||
|
{
|
||||||
|
HandleInvoke(() => handler(sender, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replacement for Invoke() on generic EventHandlers to catch exceptions that stop event propagation in case
|
||||||
|
/// of a thrown Exception inside of an invocation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eh">The EventHandler in question.</param>
|
||||||
|
/// <param name="sender">Default sender for Invoke equivalent.</param>
|
||||||
|
/// <param name="e">Default EventArgs for Invoke equivalent.</param>
|
||||||
|
/// <typeparam name="T">Type of EventArgs.</typeparam>
|
||||||
|
public static void InvokeSafely<T>(this EventHandler<T> eh, object sender, T e)
|
||||||
|
{
|
||||||
|
if (eh == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var handler in eh.GetInvocationList().Cast<EventHandler<T>>())
|
||||||
|
{
|
||||||
|
HandleInvoke(() => handler(sender, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replacement for Invoke() on event Actions to catch exceptions that stop event propagation in case
|
||||||
|
/// of a thrown Exception inside of an invocation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="act">The Action in question.</param>
|
||||||
|
public static void InvokeSafely(this Action act)
|
||||||
|
{
|
||||||
|
if (act == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var action in act.GetInvocationList().Cast<Action>())
|
||||||
|
{
|
||||||
|
HandleInvoke(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replacement for Invoke() on OnUpdateDelegate to catch exceptions that stop event propagation in case
|
||||||
|
/// of a thrown Exception inside of an invocation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updateDelegate">The OnUpdateDelegate in question.</param>
|
||||||
|
/// <param name="framework">Framework to be passed on to OnUpdateDelegate.</param>
|
||||||
|
public static void InvokeSafely(this OnUpdateDelegate updateDelegate, Framework framework)
|
||||||
|
{
|
||||||
|
if (updateDelegate == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var action in updateDelegate.GetInvocationList().Cast<OnUpdateDelegate>())
|
||||||
|
{
|
||||||
|
HandleInvoke(() => action(framework));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleInvoke(Action act)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
act();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Exception during raise of {handler}", act.Method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue