proper async events

This commit is contained in:
Matt Parker
2025-08-27 23:57:04 +10:00
parent 247989fda4
commit dd9825b629
2 changed files with 62 additions and 9 deletions

View File

@@ -7,17 +7,68 @@ namespace SharpIDE.Application.Features.Events;
public static class GlobalEvents
{
public static event Func<Task> ProjectsRunningChanged = () => Task.CompletedTask;
public static void InvokeProjectsRunningChanged() => ProjectsRunningChanged?.Invoke();
public static void InvokeProjectsRunningChanged() => ProjectsRunningChanged?.InvokeParallelFireAndForget();
public static event Func<Task> StartedRunningProject = () => Task.CompletedTask;
public static void InvokeStartedRunningProject() => StartedRunningProject?.Invoke();
public static void InvokeStartedRunningProject() => StartedRunningProject?.InvokeParallelFireAndForget();
public static event Func<SharpIdeProjectModel, Task> ProjectStartedRunning = _ => Task.CompletedTask;
public static void InvokeProjectStartedRunning(SharpIdeProjectModel project) => ProjectStartedRunning?.Invoke(project);
public static void InvokeProjectStartedRunning(SharpIdeProjectModel project) => ProjectStartedRunning?.InvokeParallelFireAndForget(project);
public static event Func<SharpIdeProjectModel, Task> ProjectStoppedRunning = _ => Task.CompletedTask;
public static void InvokeProjectStoppedRunning(SharpIdeProjectModel project) => ProjectStoppedRunning?.Invoke(project);
public static void InvokeProjectStoppedRunning(SharpIdeProjectModel project) => ProjectStoppedRunning?.InvokeParallelFireAndForget(project);
public static event Func<ExecutionStopInfo, Task> DebuggerExecutionStopped = _ => Task.CompletedTask;
public static void InvokeDebuggerExecutionStopped(ExecutionStopInfo executionStopInfo) => DebuggerExecutionStopped?.Invoke(executionStopInfo);
public static void InvokeDebuggerExecutionStopped(ExecutionStopInfo executionStopInfo) => DebuggerExecutionStopped?.InvokeParallelFireAndForget(executionStopInfo);
}
public static class AsyncEventExtensions
{
public static void InvokeParallelFireAndForget(this MulticastDelegate @event) => FireAndForget(() => @event.InvokeParallelAsync());
public static void InvokeParallelFireAndForget<T>(this MulticastDelegate @event, T arg) => FireAndForget(() => @event.InvokeParallelAsync(arg));
private static async void FireAndForget(Func<Task> action)
{
try
{
await action().ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine($"An exception occurred in an event handler: {ex}");
}
}
public static Task InvokeParallelAsync(this MulticastDelegate @event)
{
return InvokeDelegatesAsync(@event.GetInvocationList(), del => ((Func<Task>)del)());
}
public static Task InvokeParallelAsync<T>(this MulticastDelegate @event, T arg)
{
return InvokeDelegatesAsync(@event.GetInvocationList(), del => ((Func<T, Task>)del)(arg));
}
private static async Task InvokeDelegatesAsync(IEnumerable<Delegate> invocationList, Func<Delegate, Task> delegateExecutorDelegate)
{
var tasks = invocationList.Select(async del =>
{
try
{
await delegateExecutorDelegate(del).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ex;
}
});
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
var exceptions = results.Where(r => r is not null).Select(r => r!).ToList();
if (exceptions.Count != 0)
{
throw new AggregateException(exceptions);
}
}
}

View File

@@ -1,15 +1,17 @@
namespace SharpIDE.Godot;
using SharpIDE.Application.Features.Events;
namespace SharpIDE.Godot;
public static class GodotGlobalEvents
{
public static event Func<BottomPanelType, Task> BottomPanelTabExternallySelected = _ => Task.CompletedTask;
public static void InvokeBottomPanelTabExternallySelected(BottomPanelType type) => BottomPanelTabExternallySelected.Invoke(type);
public static void InvokeBottomPanelTabExternallySelected(BottomPanelType type) => BottomPanelTabExternallySelected.InvokeParallelFireAndForget(type);
public static event Func<BottomPanelType?, Task> BottomPanelTabSelected = _ => Task.CompletedTask;
public static void InvokeBottomPanelTabSelected(BottomPanelType? type) => BottomPanelTabSelected.Invoke(type);
public static void InvokeBottomPanelTabSelected(BottomPanelType? type) => BottomPanelTabSelected.InvokeParallelFireAndForget(type);
public static event Func<bool, Task> BottomPanelVisibilityChangeRequested = _ => Task.CompletedTask;
public static void InvokeBottomPanelVisibilityChangeRequested(bool show) => BottomPanelVisibilityChangeRequested.Invoke(show);
public static void InvokeBottomPanelVisibilityChangeRequested(bool show) => BottomPanelVisibilityChangeRequested.InvokeParallelFireAndForget(show);
}
public enum BottomPanelType