SyncAsyncEventArgs.IsRunningSynchronously Property


Gets a value indicating whether the event handler was invoked synchronously or asynchronously. Please see SyncAsyncEventHandler<T> for more details.

public bool IsRunningSynchronously { get; }
member this.IsRunningSynchronously : bool
Public ReadOnly Property IsRunningSynchronously As Boolean

Property Value



The same SyncAsyncEventHandler<T> event can be raised from both synchronous and asynchronous code paths depending on whether you're calling sync or async methods on a client. If you write an async handler but raise it from a sync method, the handler will be doing sync-over-async and may cause ThreadPool starvation. See Diagnosing .NET Core ThreadPool Starvation with PerfView for a detailed explanation of how that can cause ThreadPool starvation and serious performance problems.

You can use this IsRunningSynchronously property to check how the event is being raised and implement your handler accordingly. Here's an example handler that's safe to invoke from both sync and async code paths.

var client = new AlarmClient();
client.Ring += async (SyncAsyncEventArgs e) =>
    if (e.IsRunningSynchronously)
        Console.WriteLine("Wake up!");
        await Console.Out.WriteLineAsync("Wake up!");

client.Snooze(); // sync call that blocks
await client.SnoozeAsync(); // async call that doesn't block

Applies to