AsyncAwaitBestPractices 6.0.6

.NET 6.0 .NET Standard 1.0
dotnet add package AsyncAwaitBestPractices --version 6.0.6
NuGet\Install-Package AsyncAwaitBestPractices -Version 6.0.6
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AsyncAwaitBestPractices" Version="6.0.6" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AsyncAwaitBestPractices --version 6.0.6
#r "nuget: AsyncAwaitBestPractices, 6.0.6"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AsyncAwaitBestPractices as a Cake Addin
#addin nuget:?package=AsyncAwaitBestPractices&version=6.0.6

// Install AsyncAwaitBestPractices as a Cake Tool
#tool nuget:?package=AsyncAwaitBestPractices&version=6.0.6

AsyncAwaitBestPractices

NuGet

Available on NuGet: https://www.nuget.org/packages/AsyncAwaitBestPractices/

  • SafeFireAndForget
    • An extension method to safely fire-and-forget a Task or a ValueTask
    • Ensures the Task will rethrow an Exception if an Exception is caught in IAsyncStateMachine.MoveNext()
  • WeakEventManager
    • Avoids memory leaks when events are not unsubscribed
    • Used by AsyncCommand, AsyncCommand<T>, AsyncValueCommand, AsyncValueCommand<T>
  • Usage instructions

Setup

Usage

SafeFireAndForget

An extension method to safely fire-and-forget a Task.

SafeFireAndForget allows a Task to safely run on a different thread while the calling thread does not wait for its completion.

public static async void SafeFireAndForget(this System.Threading.Tasks.Task task, System.Action<System.Exception>? onException = null, bool continueOnCapturedContext = false)
public static async void SafeFireAndForget(this System.Threading.Tasks.ValueTask task, System.Action<System.Exception>? onException = null, bool continueOnCapturedContext = false)
Basic Usage - Task
void HandleButtonTapped(object sender, EventArgs e)
{
    // Allows the async Task method to safely run on a different thread while the calling thread continues, not awaiting its completion
    // onException: If an Exception is thrown, print it to the Console
    ExampleAsyncMethod().SafeFireAndForget(onException: ex => Console.WriteLine(ex));

    // HandleButtonTapped continues execution here while `ExampleAsyncMethod()` is running on a different thread
    // ...
}

async Task ExampleAsyncMethod()
{
    await Task.Delay(1000);
}
Basic Usage - ValueTask

If you're new to ValueTask, check out this great write-up, Understanding the Whys, Whats, and Whens of ValueTask.

void HandleButtonTapped(object sender, EventArgs e)
{
    // Allows the async ValueTask method to safely run on a different thread while the calling thread continues, not awaiting its completion
    // onException: If an Exception is thrown, print it to the Console
    ExampleValueTaskMethod().SafeFireAndForget(onException: ex => Console.WriteLine(ex));

    // HandleButtonTapped continues execution here while `ExampleAsyncMethod()` is running on a different thread
    // ...
}

async ValueTask ExampleValueTaskMethod()
{
    var random = new Random();
    if (random.Next(10) > 9)
        await Task.Delay(1000);
}
Advanced Usage
void InitializeSafeFireAndForget()
{
    // Initialize SafeFireAndForget
    // Only use `shouldAlwaysRethrowException: true` when you want `.SafeFireAndForget()` to always rethrow every exception. This is not recommended, because there is no way to catch an Exception rethrown by `SafeFireAndForget()`; `shouldAlwaysRethrowException: true` should **not** be used in Production/Release builds.
    SafeFireAndForgetExtensions.Initialize(shouldAlwaysRethrowException: false);

    // SafeFireAndForget will print every exception to the Console
    SafeFireAndForgetExtensions.SetDefaultExceptionHandling(ex => Console.WriteLine(ex));
}

void UninitializeSafeFireAndForget()
{
    // Remove default exception handling
    SafeFireAndForgetExtensions.RemoveDefaultExceptionHandling()
}

void HandleButtonTapped(object sender, EventArgs e)
{
    // Allows the async Task method to safely run on a different thread while not awaiting its completion
    // onException: If a WebException is thrown, print its StatusCode to the Console. **Note**: If a non-WebException is thrown, it will not be handled by `onException`
    // Because we set `SetDefaultExceptionHandling` in `void InitializeSafeFireAndForget()`, the entire exception will also be printed to the Console
    ExampleAsyncMethod().SafeFireAndForget<WebException>(onException: ex =>
    {
        if(ex.Response is HttpWebResponse webResponse)
            Console.WriteLine($"Task Exception\n Status Code: {webResponse.StatusCode}");
    });
    
    ExampleValueTaskMethod().SafeFireAndForget<WebException>(onException: ex =>
    {
        if(ex.Response is HttpWebResponse webResponse)
            Console.WriteLine($"ValueTask Error\n Status Code: {webResponse.StatusCode}");
    });

    // HandleButtonTapped continues execution here while `ExampleAsyncMethod()` and `ExampleValueTaskMethod()` run in the background
}

async Task ExampleAsyncMethod()
{
    await Task.Delay(1000);
    throw new WebException();
}

async ValueTask ExampleValueTaskMethod()
{
    var random = new Random();
    if (random.Next(10) > 9)
        await Task.Delay(1000);
        
    throw new WebException();
}

WeakEventManager

An event implementation that enables the garbage collector to collect an object without needing to unsubscribe event handlers.

Inspired by Xamarin.Forms.WeakEventManager.

Using EventHandler
readonly WeakEventManager _canExecuteChangedEventManager = new WeakEventManager();

public event EventHandler CanExecuteChanged
{
    add => _canExecuteChangedEventManager.AddEventHandler(value);
    remove => _canExecuteChangedEventManager.RemoveEventHandler(value);
}

void OnCanExecuteChanged() => _canExecuteChangedEventManager.RaiseEvent(this, EventArgs.Empty, nameof(CanExecuteChanged));
Using Delegate
readonly WeakEventManager _propertyChangedEventManager = new WeakEventManager();

public event PropertyChangedEventHandler PropertyChanged
{
    add => _propertyChangedEventManager.AddEventHandler(value);
    remove => _propertyChangedEventManager.RemoveEventHandler(value);
}

void OnPropertyChanged([CallerMemberName]string propertyName = "") => _propertyChangedEventManager.RaiseEvent(this, new PropertyChangedEventArgs(propertyName), nameof(PropertyChanged));
Using Action
readonly WeakEventManager _weakActionEventManager = new WeakEventManager();

public event Action ActionEvent
{
    add => _weakActionEventManager.AddEventHandler(value);
    remove => _weakActionEventManager.RemoveEventHandler(value);
}

void OnActionEvent(string message) => _weakActionEventManager.RaiseEvent(message, nameof(ActionEvent));

WeakEventManager<T>

An event implementation that enables the garbage collector to collect an object without needing to unsubscribe event handlers.

Inspired by Xamarin.Forms.WeakEventManager.

Using EventHandler<T>
readonly WeakEventManager<string> _errorOcurredEventManager = new WeakEventManager<string>();

public event EventHandler<string> ErrorOcurred
{
    add => _errorOcurredEventManager.AddEventHandler(value);
    remove => _errorOcurredEventManager.RemoveEventHandler(value);
}

void OnErrorOcurred(string message) => _errorOcurredEventManager.RaiseEvent(this, message, nameof(ErrorOcurred));
Using Action<T>
readonly WeakEventManager<string> _weakActionEventManager = new WeakEventManager<string>();

public event Action<string> ActionEvent
{
    add => _weakActionEventManager.AddEventHandler(value);
    remove => _weakActionEventManager.RemoveEventHandler(value);
}

void OnActionEvent(string message) => _weakActionEventManager.RaiseEvent(message, nameof(ActionEvent));
Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp1.0 netcoreapp1.1 netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 netstandard2.1
.NET Framework net45 net451 net452 net46 net461 net462 net463 net47 net471 net472 net48 net481
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen30 tizen40 tizen60
Universal Windows Platform uap uap10.0
Windows Phone wp8 wp81 wpa81
Windows Store netcore netcore45 netcore451
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (9)

Showing the top 5 NuGet packages that depend on AsyncAwaitBestPractices:

Package Downloads
AsyncAwaitBestPractices.MVVM

Async Extensions for ICommand Includes AsyncCommand and IAsyncCommand which allows ICommand to safely be used asynchronously with Task. Includes AsyncValueCommand and IAsyncValueCommand which allows ICommand to safely be used asynchronously with ValueTask

Xam.Shell.Badge

A small plugin to ease the use of badges on Shell Bottom Bars

Mopups

Popups for MAUI

HB.FullStack.Common

Package Description

AppHosting.Xamarin.Forms.iOS

Package Description

GitHub repositories (8)

Showing the top 5 popular GitHub repositories that depend on AsyncAwaitBestPractices:

Repository Stars
beeradmoore/dlss-swapper
brminnick/GitTrends
A iOS and Android app to monitor the Views, Clones and Star history of your GitHub repos
DaxStudio/DaxStudio
DAX Studio is a tool to write, execute, and analyze DAX queries in Power BI Desktop, Power Pivot for Excel, and Analysis Services Tabular.
Azure/Industrial-IoT
Azure Industrial IoT Platform
mehdihadeli/ecommerce-microservices
🛍️ A practical e-commerce microservices, built with .Net 7, Domain-Driven Design, CQRS, Vertical Slice Architecture, Event-Driven Architecture, and the latest technologies.
Version Downloads Last updated
6.0.6 39,961 11/12/2022
6.0.5 58,230 7/3/2022
6.0.4 157,162 11/23/2021
6.0.3 5,499 11/11/2021
6.0.2 14,388 10/12/2021
6.0.1 13,360 9/27/2021
6.0.0 34,611 7/3/2021
6.0.0-pre1 727 6/7/2021
5.1.0 91,404 3/13/2021
5.0.2 118,463 11/2/2020
5.0.0-pre2 1,609 9/17/2020
5.0.0-pre1 362 9/17/2020
4.3.0 25,771 9/15/2020
4.3.0-pre1 1,609 7/29/2020
4.2.0 39,381 7/13/2020
4.1.1 40,481 5/15/2020
4.1.1-pre1 2,224 4/1/2020
4.1.0 74,220 1/30/2020
4.1.0-pre2 1,056 1/7/2020
4.1.0-pre1 912 12/19/2019
4.0.1 88,872 12/13/2019
4.0.0-pre3 708 11/29/2019
4.0.0-pre1 440 11/7/2019
3.1.0 28,231 8/28/2019
3.1.0-pre5 732 8/20/2019
3.1.0-pre4 477 8/20/2019
3.1.0-pre3 535 8/14/2019
3.1.0-pre2 666 7/31/2019
3.1.0-pre1 517 7/31/2019
3.0.0 5,650 7/30/2019
3.0.0-pre4 588 7/14/2019
3.0.0-pre3 509 7/7/2019
3.0.0-pre2 577 7/2/2019
3.0.0-pre1 620 6/9/2019
2.1.1 18,240 4/17/2019
2.1.0 4,403 1/12/2019
2.1.0-pre1 906 12/27/2018
2.0.0 992 12/19/2018
1.2.1 846 12/17/2018
1.2.0 661 12/17/2018
1.1.0 847 12/16/2018
1.0.1 857 12/15/2018
1.0.0 784 11/30/2018
0.9.0 1,256 11/22/2018

New In This Release:
- Add .NET 7.0 Target