Skip to content

Commit

Permalink
Merge pull request #34 from brminnick/Release-v4.1.1
Browse files Browse the repository at this point in the history
Release v4.1.1
  • Loading branch information
brminnick authored Apr 1, 2020
2 parents 4944aa6 + 4edcd69 commit e0e50bd
Show file tree
Hide file tree
Showing 12 changed files with 229 additions and 87 deletions.
12 changes: 4 additions & 8 deletions Src/AsyncAwaitBestPractices.MVVM.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="2.5">
<id>AsyncAwaitBestPractices.MVVM</id>
<version>4.1.0</version>
<version>4.1.1</version>
<title>Async Extensions for ICommand</title>
<authors>Brandon Minnick, John Thiriet</authors>
<owners>Brandon Minnick</owners>
Expand All @@ -24,18 +24,14 @@
</summary>
<tags>task, valuetask, fire and forget, threading, extensions, system.threading.tasks, async, await</tags>
<dependencies>
<dependency id="AsyncAwaitBestPractices" version="4.1.0" />
<dependency id="AsyncAwaitBestPractices" version="4.1.1" />
</dependencies>
<releaseNotes>
New In This Release:
- Unseal AsyncCommand
- Unseal AsyncCommand&lt;T&gt;
- Unseal AsyncValueCommand
- Unseal AsyncValueCommand&lt;T&gt;
- Include Assembly Signing
- Add Extension Methods Without `in` Keyword (provides support for older versions of Visual Studio)
</releaseNotes>
<repository type="git" url="https://github.com/brminnick/AsyncAwaitBestPractices.git" branch="master" commit="8966e2ec7aa3e325256dd4c8acd01073646471de" />
<copyright>Copyright (c) 2018 Brandon Minnick</copyright>
<copyright>Copyright (c) 2020 Brandon Minnick</copyright>
</metadata>
<files>
<file src="AsyncAwaitBestPractices.MVVM\bin\Release\netstandard1.0\AsyncAwaitBestPractices.MVVM.pdb" target="lib\netstandard1.0\AsyncAwaitBestPractices.MVVM.pdb" />
Expand Down
6 changes: 3 additions & 3 deletions Src/AsyncAwaitBestPractices.MVVM/AsyncCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ void ICommand.Execute(object parameter)
switch (parameter)
{
case T validParameter:
ExecuteAsync(validParameter).SafeFireAndForget(_onException, _continueOnCapturedContext);
ExecuteAsync(validParameter).SafeFireAndForget(_onException, in _continueOnCapturedContext);
break;

#pragma warning disable CS8604 // Possible null reference argument.
case null when !typeof(T).GetTypeInfo().IsValueType:
ExecuteAsync((T)parameter).SafeFireAndForget(_onException, _continueOnCapturedContext);
ExecuteAsync((T)parameter).SafeFireAndForget(_onException, in _continueOnCapturedContext);
break;
#pragma warning restore CS8604 // Possible null reference argument.

Expand Down Expand Up @@ -141,6 +141,6 @@ public event EventHandler CanExecuteChanged
/// <returns>The executed Task</returns>
public Task ExecuteAsync() => _execute();

void ICommand.Execute(object parameter) => _execute().SafeFireAndForget(_onException, _continueOnCapturedContext);
void ICommand.Execute(object parameter) => _execute().SafeFireAndForget(_onException, in _continueOnCapturedContext);
}
}
18 changes: 9 additions & 9 deletions Src/AsyncAwaitBestPractices.MVVM/AsyncValueCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public class AsyncValueCommand<T> : IAsyncValueCommand<T>
/// <param name="onException">If an exception is thrown in the Task, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c> continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c> continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
public AsyncValueCommand(Func<T, ValueTask> execute,
Func<object?, bool>? canExecute = null,
Action<Exception>? onException = null,
bool continueOnCapturedContext = false)
Func<object?, bool>? canExecute = null,
Action<Exception>? onException = null,
bool continueOnCapturedContext = false)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute), $"{nameof(execute)} cannot be null");
_canExecute = canExecute ?? (_ => true);
Expand Down Expand Up @@ -67,11 +67,11 @@ void ICommand.Execute(object parameter)
switch (parameter)
{
case T validParameter:
ExecuteAsync(validParameter).SafeFireAndForget(_onException, _continueOnCapturedContext);
ExecuteAsync(validParameter).SafeFireAndForget(_onException, in _continueOnCapturedContext);
break;
#pragma warning disable CS8604 // Possible null reference argument.
case null when !typeof(T).GetTypeInfo().IsValueType:
ExecuteAsync((T)parameter).SafeFireAndForget(_onException, _continueOnCapturedContext);
ExecuteAsync((T)parameter).SafeFireAndForget(_onException, in _continueOnCapturedContext);
break;
#pragma warning restore CS8604 // Possible null reference argument.

Expand Down Expand Up @@ -103,9 +103,9 @@ public class AsyncValueCommand : IAsyncValueCommand
/// <param name="onException">If an exception is thrown in the Task, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c> continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c> continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
public AsyncValueCommand(Func<ValueTask> execute,
Func<object?, bool>? canExecute = null,
Action<Exception>? onException = null,
bool continueOnCapturedContext = false)
Func<object?, bool>? canExecute = null,
Action<Exception>? onException = null,
bool continueOnCapturedContext = false)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute), $"{nameof(execute)} cannot be null");
_canExecute = canExecute ?? (_ => true);
Expand Down Expand Up @@ -140,6 +140,6 @@ public event EventHandler CanExecuteChanged
/// <returns>The executed Task</returns>
public ValueTask ExecuteAsync() => _execute();

void ICommand.Execute(object parameter) => _execute().SafeFireAndForget(_onException, _continueOnCapturedContext);
void ICommand.Execute(object parameter) => _execute().SafeFireAndForget(_onException, in _continueOnCapturedContext);
}
}
26 changes: 11 additions & 15 deletions Src/AsyncAwaitBestPractices.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="2.5">
<id>AsyncAwaitBestPractices</id>
<version>4.1.0</version>
<version>4.1.1</version>
<title>Task Extensions for System.Threading.Tasks</title>
<authors>Brandon Minnick, John Thiriet</authors>
<owners>Brandon Minnick</owners>
Expand All @@ -25,42 +25,38 @@
<tags>task,fire and forget, threading, extensions, system.threading.tasks,async,await</tags>
<dependencies>
<group targetFramework="netstandard1.0">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.1">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.2">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.3">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.4">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.5">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard1.6">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard2.0">
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3"/>
<dependency id="System.Threading.Tasks.Extensions" version="4.5.4"/>
</group>
<group targetFramework="netstandard2.1">
</group>
</dependencies>
<releaseNotes>
New In This Release:
- Add SafeFireAndForget(Action&lt;Exception&gt; onException, bool continueOnCapturedContext)
- Add SafeFireAndForget&lt;TException&gt;(Action&lt;Exception&gt; onException, bool continueOnCapturedContext)
- Obsolete: SafeFireAndForget(bool continueOnCapturedContext, Action&lt;Exception&gt; onException)
- Obsolete: SafeFireAndForget&lt;TException&gt;(bool continueOnCapturedContext, Action&lt;TException&gt; onException)
- Include Assembly Signing
- Add Extension Methods Without `in` Keyword (provides support for older versions of Visual Studio)
</releaseNotes>
<repository type="git" url="https://github.com/brminnick/AsyncAwaitBestPractices.git" branch="master" commit="8966e2ec7aa3e325256dd4c8acd01073646471de" />
<copyright>Copyright (c) 2018 Brandon Minnick</copyright>
<copyright>Copyright (c) 2020 Brandon Minnick</copyright>
</metadata>
<files>
<file src="AsyncAwaitBestPractices\bin\Release\netstandard1.0\AsyncAwaitBestPractices.pdb" target="lib\netstandard1.0\AsyncAwaitBestPractices.pdb" />
Expand Down
2 changes: 1 addition & 1 deletion Src/AsyncAwaitBestPractices/AsyncAwaitBestPractices.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<DocumentationFile>bin\Release\netstandard1.0\AsyncAwaitBestPractices.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>
<ItemGroup>
<Folder Include="WeakEventManager\" />
Expand Down
44 changes: 1 addition & 43 deletions Src/AsyncAwaitBestPractices/SafeFireAndForgetExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace AsyncAwaitBestPractices
/// <summary>
/// Extension methods for System.Threading.Tasks.Task and System.Threading.Tasks.ValueTask
/// </summary>
public static class SafeFireAndForgetExtensions
public static partial class SafeFireAndForgetExtensions
{
static Action<Exception>? _onException;
static bool _shouldAlwaysRethrowException;
Expand Down Expand Up @@ -47,48 +47,8 @@ public static class SafeFireAndForgetExtensions
/// <typeparam name="TException">Exception type. If an exception is thrown of a different type, it will not be handled</typeparam>
public static void SafeFireAndForget<TException>(this Task task, in Action<TException>? onException = null, in bool continueOnCapturedContext = false) where TException : Exception => HandleSafeFireAndForget(task, continueOnCapturedContext, onException);

#region Obsolete Methods
/// <summary>
/// Safely execute the ValueTask without waiting for it to complete before moving to the next line of code; commonly known as "Fire And Forget". Inspired by John Thiriet's blog post, "Removing Async Void": https://johnthiriet.com/removing-async-void/.
/// </summary>
/// <param name="task">ValueTask.</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c>, continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c>, continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
/// <param name="onException">If an exception is thrown in the ValueTask, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
[Obsolete("Use SafeFireAndForget(Action<Exception> onException, bool continueOnCapturedContext)")]
public static void SafeFireAndForget(this ValueTask task, in bool continueOnCapturedContext, in Action<Exception>? onException) => HandleSafeFireAndForget(task, continueOnCapturedContext, onException);


/// <summary>
/// Safely execute the ValueTask without waiting for it to complete before moving to the next line of code; commonly known as "Fire And Forget". Inspired by John Thiriet's blog post, "Removing Async Void": https://johnthiriet.com/removing-async-void/.
/// </summary>
/// <param name="task">ValueTask.</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c>, continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c>, continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
/// <param name="onException">If an exception is thrown in the Task, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
/// <typeparam name="TException">Exception type. If an exception is thrown of a different type, it will not be handled</typeparam>
[Obsolete("Use SafeFireAndForget<TException>(Action<TException> onException, bool continueOnCapturedContext)")]
public static void SafeFireAndForget<TException>(this ValueTask task, in bool continueOnCapturedContext, in Action<TException>? onException) where TException : Exception => HandleSafeFireAndForget(task, continueOnCapturedContext, onException);


/// <summary>
/// Safely execute the Task without waiting for it to complete before moving to the next line of code; commonly known as "Fire And Forget". Inspired by John Thiriet's blog post, "Removing Async Void": https://johnthiriet.com/removing-async-void/.
/// </summary>
/// <param name="task">Task.</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c>, continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c>, continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
/// <param name="onException">If an exception is thrown in the Task, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
[Obsolete("Use SafeFireAndForget(Action<Exception> onException, bool continueOnCapturedContext)")]
public static void SafeFireAndForget(this Task task, in bool continueOnCapturedContext, in Action<Exception>? onException) => HandleSafeFireAndForget(task, continueOnCapturedContext, onException);

/// <summary>
/// Safely execute the Task without waiting for it to complete before moving to the next line of code; commonly known as "Fire And Forget". Inspired by John Thiriet's blog post, "Removing Async Void": https://johnthiriet.com/removing-async-void/.
/// </summary>
/// <param name="task">Task.</param>
/// <param name="continueOnCapturedContext">If set to <c>true</c>, continue on captured context; this will ensure that the Synchronization Context returns to the calling thread. If set to <c>false</c>, continue on a different context; this will allow the Synchronization Context to continue on a different thread</param>
/// <param name="onException">If an exception is thrown in the Task, <c>onException</c> will execute. If onException is null, the exception will be re-thrown</param>
/// <typeparam name="TException">Exception type. If an exception is thrown of a different type, it will not be handled</typeparam>
[Obsolete("Use SafeFireAndForget<TException>(Action<TException> onException, bool continueOnCapturedContext)")]
public static void SafeFireAndForget<TException>(this Task task, in bool continueOnCapturedContext, in Action<TException>? onException) where TException : Exception => HandleSafeFireAndForget(task, continueOnCapturedContext, onException);
#endregion

/// <summary>
/// Initialize SafeFireAndForget
///
Expand All @@ -114,7 +74,6 @@ public static void SetDefaultExceptionHandling(in Action<Exception> onException)
_onException = onException;
}

#pragma warning disable RECS0165 // Asynchronous methods should return a Task instead of void
static async void HandleSafeFireAndForget<TException>(ValueTask valueTask, bool continueOnCapturedContext, Action<TException>? onException) where TException : Exception
{
try
Expand Down Expand Up @@ -144,7 +103,6 @@ static async void HandleSafeFireAndForget<TException>(Task task, bool continueOn
throw;
}
}
#pragma warning restore RECS0165 // Asynchronous methods should return a Task instead of void

static void HandleException<TException>(in TException exception, in Action<TException>? onException) where TException : Exception
{
Expand Down
Loading

0 comments on commit e0e50bd

Please sign in to comment.