Skip to content

Commit

Permalink
Update SyncAsyncEventArgs APIs (Azure#18437)
Browse files Browse the repository at this point in the history
  • Loading branch information
pakrym authored and jongio committed Feb 9, 2021
1 parent 9392017 commit d9f774e
Show file tree
Hide file tree
Showing 19 changed files with 63 additions and 63 deletions.
4 changes: 2 additions & 2 deletions sdk/core/Azure.Core/api/Azure.Core.net461.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ protected Response() { }
}
public partial class SyncAsyncEventArgs : System.EventArgs
{
public SyncAsyncEventArgs(bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public SyncAsyncEventArgs(bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } }
public bool RunSynchronously { get { throw null; } }
public bool IsRunningSynchronously { get { throw null; } }
}
}
namespace Azure.Core
Expand Down
4 changes: 2 additions & 2 deletions sdk/core/Azure.Core/api/Azure.Core.net5.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ protected Response() { }
}
public partial class SyncAsyncEventArgs : System.EventArgs
{
public SyncAsyncEventArgs(bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public SyncAsyncEventArgs(bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } }
public bool RunSynchronously { get { throw null; } }
public bool IsRunningSynchronously { get { throw null; } }
}
}
namespace Azure.Core
Expand Down
4 changes: 2 additions & 2 deletions sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ protected Response() { }
}
public partial class SyncAsyncEventArgs : System.EventArgs
{
public SyncAsyncEventArgs(bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public SyncAsyncEventArgs(bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } }
public bool RunSynchronously { get { throw null; } }
public bool IsRunningSynchronously { get { throw null; } }
}
}
namespace Azure.Core
Expand Down
12 changes: 6 additions & 6 deletions sdk/core/Azure.Core/samples/Events.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ that contain important information for writing your event handler.
`new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token`, for example)
will correctly propagate.

- There is a `SyncAsyncEventArgs.RunSynchronously` flag indicating whether your
- There is a `SyncAsyncEventArgs.IsRunningSynchronously` flag indicating whether your
handler was invoked synchronously or asynchronously. In general,

- If you're calling sync methods on your client, you should use sync methods
to implement your event handler. You can return `Task.CompletedTask`.
- If you're calling async methods on your client, you should use async
methods where possible to implement your event handler.
- If you're not in control of how the client will be used or want to write
safer code, you should check the `RunSynchronously` property and call
safer code, you should check the `IsRunningSynchronously` property and call
either sync or async methods as directed.

There are code examples of all three situations below to compare. Please also
see the note at the very end discussing the dangers of sync-over-async to
understand the risks of not using the `RunSynchronously` flag.
understand the risks of not using the `IsRunningSynchronously` flag.

- Most events will customize the event data by deriving from `SyncAsyncEventArgs`
and including details about what triggered the event or providing options to
Expand Down Expand Up @@ -125,15 +125,15 @@ 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 the note at the
bottom for more details.

You should use the `SyncAsyncEventArgs.RunSynchronously` property to check how
You should use the `SyncAsyncEventArgs.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.

```C# Snippet:Azure_Core_Samples_EventSamples_CombinedHandler
var client = new AlarmClient();
client.Ring += async (SyncAsyncEventArgs e) =>
{
if (e.RunSynchronously)
if (e.IsRunningSynchronously)
{
Console.WriteLine("Wake up!");
}
Expand Down Expand Up @@ -180,7 +180,7 @@ sync-over-async because you're getting sync behavior but still invoking all the
async machinery. See
[Diagnosing .NET Core ThreadPool Starvation with PerfView](https://docs.microsoft.com/archive/blogs/vancem/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall)
for a detailed explanation of how that can cause serious performance problems.
We recommend you use the `SyncAsyncEventArgs.RunSynchronously` flag to avoid
We recommend you use the `SyncAsyncEventArgs.IsRunningSynchronously` flag to avoid
ThreadPool starvation.

But what about executing synchronous code on an async code path like the "Adding
Expand Down
12 changes: 6 additions & 6 deletions sdk/core/Azure.Core/src/SyncAsyncEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ public class SyncAsyncEventArgs : EventArgs
/// and serious performance problems.
/// </para>
/// <para>
/// You can use this <see cref="RunSynchronously"/> property to check
/// You can use this <see cref="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.
/// <code snippet="Snippet:Azure_Core_Samples_EventSamples_CombinedHandler">
/// var client = new AlarmClient();
/// client.Ring += async (SyncAsyncEventArgs e) =&gt;
/// {
/// if (e.RunSynchronously)
/// if (e.IsRunningSynchronously)
/// {
/// Console.WriteLine(&quot;Wake up!&quot;);
/// }
Expand All @@ -54,7 +54,7 @@ public class SyncAsyncEventArgs : EventArgs
/// </code>
/// </para>
/// </remarks>
public bool RunSynchronously { get; }
public bool IsRunningSynchronously { get; }

/// <summary>
/// Gets a cancellation token related to the original operation that
Expand All @@ -72,7 +72,7 @@ public class SyncAsyncEventArgs : EventArgs
/// Initializes a new instance of the <see cref="SyncAsyncEventArgs"/>
/// class.
/// </summary>
/// <param name="runSynchronously">
/// <param name="isRunningSynchronously">
/// A value indicating whether the event handler was invoked
/// synchronously or asynchronously. Please see
/// <see cref="Azure.Core.SyncAsyncEventHandler{T}"/> for more details.
Expand All @@ -84,10 +84,10 @@ public class SyncAsyncEventArgs : EventArgs
/// that take a token so cancellation will correctly propagate. The
/// default value is <see cref="CancellationToken.None"/>.
/// </param>
public SyncAsyncEventArgs(bool runSynchronously, CancellationToken cancellationToken = default)
public SyncAsyncEventArgs(bool isRunningSynchronously, CancellationToken cancellationToken = default)
: base()
{
RunSynchronously = runSynchronously;
IsRunningSynchronously = isRunningSynchronously;
CancellationToken = cancellationToken;
}
}
Expand Down
10 changes: 5 additions & 5 deletions sdk/core/Azure.Core/src/SyncAsyncEventHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ namespace Azure.Core
/// 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 the note in Remarks for more details. You
/// should use the <see cref="SyncAsyncEventArgs.RunSynchronously"/>
/// should use the <see cref="SyncAsyncEventArgs.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.
/// <code snippet="Snippet:Azure_Core_Samples_EventSamples_CombinedHandler">
/// var client = new AlarmClient();
/// client.Ring += async (SyncAsyncEventArgs e) =&gt;
/// {
/// if (e.RunSynchronously)
/// if (e.IsRunningSynchronously)
/// {
/// Console.WriteLine(&quot;Wake up!&quot;);
/// }
Expand Down Expand Up @@ -158,15 +158,15 @@ namespace Azure.Core
/// </item>
/// <item>
/// <description>
/// <see cref="SyncAsyncEventArgs.RunSynchronously"/> is a flag indicating
/// <see cref="SyncAsyncEventArgs.IsRunningSynchronously"/> is a flag indicating
/// whether your handler was invoked synchronously or asynchronously. If
/// you're calling sync methods on your client, you should use sync methods
/// to implement your event handler (you can return
/// <see cref="Task.CompletedTask"/>). If you're calling async methods on
/// your client, you should use async methods where possible to implement
/// your event handler. If you're not in control of how the client will be
/// used or want to write safer code, you should check the
/// <see cref="SyncAsyncEventArgs.RunSynchronously"/> property and call
/// <see cref="SyncAsyncEventArgs.IsRunningSynchronously"/> property and call
/// either sync or async methods as directed.
/// </description>
/// </item>
Expand Down Expand Up @@ -214,7 +214,7 @@ namespace Azure.Core
/// Diagnosing.NET Core ThreadPool Starvation with PerfView</see>
/// for a detailed explanation of how that can cause serious performance
/// problems. We recommend you use the
/// <see cref="SyncAsyncEventArgs.RunSynchronously"/> flag to avoid
/// <see cref="SyncAsyncEventArgs.IsRunningSynchronously"/> flag to avoid
/// ThreadPool starvation.
/// </para>
/// </remarks>
Expand Down
18 changes: 9 additions & 9 deletions sdk/core/Azure.Core/tests/SyncAsyncEventHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class TestSyncAsyncEventArgs : SyncAsyncEventArgs
{
public TestClient Client { get; }
public int Result { get; }
public TestSyncAsyncEventArgs(TestClient client, int result, bool runSynchronously, CancellationToken cancellationToken = default)
: base(runSynchronously, cancellationToken)
public TestSyncAsyncEventArgs(TestClient client, int result, bool isRunningSynchronously, CancellationToken cancellationToken = default)
: base(isRunningSynchronously, cancellationToken)
{
Client = client;
Result = result;
Expand All @@ -46,17 +46,17 @@ public TestClient() : this(null) { }
public virtual event SyncAsyncEventHandler<SyncAsyncEventArgs> Working;
public virtual event SyncAsyncEventHandler<TestSyncAsyncEventArgs> WorkCompleted;

protected virtual async Task OnWorkingAsync(bool runSynchronously, CancellationToken cancellationToken) =>
protected virtual async Task OnWorkingAsync(bool isRunningSynchronously, CancellationToken cancellationToken) =>
await Working.RaiseAsync(
new SyncAsyncEventArgs(runSynchronously, cancellationToken),
new SyncAsyncEventArgs(isRunningSynchronously, cancellationToken),
nameof(TestClient),
nameof(Working),
ClientDiagnostics)
.ConfigureAwait(false);

protected virtual async Task OnWorkCompletedAsync(int result, bool runSynchronously, CancellationToken cancellationToken) =>
protected virtual async Task OnWorkCompletedAsync(int result, bool isRunningSynchronously, CancellationToken cancellationToken) =>
await WorkCompleted.RaiseAsync(
new TestSyncAsyncEventArgs(this, result, runSynchronously, cancellationToken),
new TestSyncAsyncEventArgs(this, result, isRunningSynchronously, cancellationToken),
nameof(TestClient),
nameof(Working),
ClientDiagnostics)
Expand Down Expand Up @@ -121,7 +121,7 @@ public async Task Handle(T e)

if (Delay != null)
{
if (e.RunSynchronously)
if (e.IsRunningSynchronously)
{
e.CancellationToken.WaitHandle.WaitOne(Delay.Value);
}
Expand All @@ -134,7 +134,7 @@ public async Task Handle(T e)
Func<bool, CancellationToken, Task> callback = Callback;
if (callback != null)
{
await callback(e.RunSynchronously, e.CancellationToken);
await callback(e.IsRunningSynchronously, e.CancellationToken);
}

if (Throws != null)
Expand Down Expand Up @@ -453,7 +453,7 @@ public async Task SequentialProcessing()
{
text.Append(before);
TimeSpan delay = TimeSpan.FromMilliseconds(50);
if (e.RunSynchronously)
if (e.IsRunningSynchronously)
{
e.CancellationToken.WaitHandle.WaitOne(delay);
}
Expand Down
8 changes: 4 additions & 4 deletions sdk/core/Azure.Core/tests/samples/EventSamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ public void Snooze(CancellationToken cancellationToken = default) =>
public async Task SnoozeAsync(CancellationToken cancellationToken = default) =>
await SnoozeInternal(false, cancellationToken).ConfigureAwait(false);

protected virtual async Task SnoozeInternal(bool runSynchronously, CancellationToken cancellationToken)
protected virtual async Task SnoozeInternal(bool isRunningSynchronously, CancellationToken cancellationToken)
{
// Why does snoozing an alarm always wait 9 minutes?
TimeSpan delay = TimeSpan.FromMilliseconds(900);
if (runSynchronously)
if (isRunningSynchronously)
{
cancellationToken.WaitHandle.WaitOne(delay);
}
else
{
await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
}
SyncAsyncEventArgs e = new SyncAsyncEventArgs(runSynchronously, cancellationToken);
SyncAsyncEventArgs e = new SyncAsyncEventArgs(isRunningSynchronously, cancellationToken);
await Ring.RaiseAsync(e, nameof(AlarmClient), nameof(Ring), _clientDiagnostics).ConfigureAwait(false);
}
}
Expand Down Expand Up @@ -77,7 +77,7 @@ public async Task CombinedHandler()
var client = new AlarmClient();
client.Ring += async (SyncAsyncEventArgs e) =>
{
if (e.RunSynchronously)
if (e.IsRunningSynchronously)
{
Console.WriteLine("Wake up!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2199,18 +2199,18 @@ public enum FacetType
}
public partial class IndexActionCompletedEventArgs<T> : Azure.Search.Documents.Models.IndexActionEventArgs<T>
{
public IndexActionCompletedEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, Azure.Search.Documents.Models.IndexingResult result, bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(Azure.Search.Documents.SearchIndexingBufferedSender<T>), default(Azure.Search.Documents.Models.IndexDocumentsAction<T>), default(bool), default(System.Threading.CancellationToken)) { }
public IndexActionCompletedEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, Azure.Search.Documents.Models.IndexingResult result, bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(Azure.Search.Documents.SearchIndexingBufferedSender<T>), default(Azure.Search.Documents.Models.IndexDocumentsAction<T>), default(bool), default(System.Threading.CancellationToken)) { }
public Azure.Search.Documents.Models.IndexingResult Result { get { throw null; } }
}
public partial class IndexActionEventArgs<T> : Azure.SyncAsyncEventArgs
{
public IndexActionEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(bool), default(System.Threading.CancellationToken)) { }
public IndexActionEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(bool), default(System.Threading.CancellationToken)) { }
public Azure.Search.Documents.Models.IndexDocumentsAction<T> Action { get { throw null; } }
public Azure.Search.Documents.SearchIndexingBufferedSender<T> Sender { get { throw null; } }
}
public partial class IndexActionFailedEventArgs<T> : Azure.Search.Documents.Models.IndexActionEventArgs<T>
{
public IndexActionFailedEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, Azure.Search.Documents.Models.IndexingResult result, System.Exception exception, bool runSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(Azure.Search.Documents.SearchIndexingBufferedSender<T>), default(Azure.Search.Documents.Models.IndexDocumentsAction<T>), default(bool), default(System.Threading.CancellationToken)) { }
public IndexActionFailedEventArgs(Azure.Search.Documents.SearchIndexingBufferedSender<T> sender, Azure.Search.Documents.Models.IndexDocumentsAction<T> action, Azure.Search.Documents.Models.IndexingResult result, System.Exception exception, bool isRunningSynchronously, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) : base (default(Azure.Search.Documents.SearchIndexingBufferedSender<T>), default(Azure.Search.Documents.Models.IndexDocumentsAction<T>), default(bool), default(System.Threading.CancellationToken)) { }
public System.Exception Exception { get { throw null; } }
public Azure.Search.Documents.Models.IndexingResult Result { get { throw null; } }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class IndexActionCompletedEventArgs<T> : IndexActionEventArgs<T>
/// The <see cref="IndexingResult"/> of an action that was successfully
/// completed.
/// </param>
/// <param name="runSynchronously">
/// <param name="isRunningSynchronously">
/// A value indicating whether the event handler was invoked
/// synchronously or asynchronously. Please see
/// <see cref="Azure.Core.SyncAsyncEventHandler{T}"/> for more details.
Expand All @@ -57,9 +57,9 @@ public IndexActionCompletedEventArgs(
SearchIndexingBufferedSender<T> sender,
IndexDocumentsAction<T> action,
IndexingResult result,
bool runSynchronously,
bool isRunningSynchronously,
CancellationToken cancellationToken = default)
: base(sender, action, runSynchronously, cancellationToken)
: base(sender, action, isRunningSynchronously, cancellationToken)
{
Argument.AssertNotNull(result, nameof(result));
Result = result;
Expand Down
Loading

0 comments on commit d9f774e

Please sign in to comment.