Skip to content

Commit 5f169aa

Browse files
Merge branch 'Release-v4.0.0' of https://github.com/brminnick/AsyncAwaitBestPractices into Release-v4.0.0
2 parents ba8a1c4 + 34b1877 commit 5f169aa

File tree

1 file changed

+109
-9
lines changed

1 file changed

+109
-9
lines changed

README.md

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,28 +317,24 @@ void OnActionEvent(string message) => _weakActionEventManager.HandleEvent(messag
317317

318318
### `AsyncCommand`
319319

320-
Allows for `Task` and `ValueTask` to safely be used asynchronously with `ICommand`:
320+
Allows for `Task` to safely be used asynchronously with `ICommand`:
321321

322322
- `AsyncCommand<T> : IAsyncCommand<T>`
323323
- `IAsyncCommand<T> : ICommand`
324324
- `AsyncCommand : IAsyncCommand`
325325
- `IAsyncCommand : ICommand`
326-
- `AsyncValueCommand<T> : IAsyncValueCommand<T>`
327-
- `IAsyncValueCommand<T> : ICommand`
328-
- `AsyncValueCommand : IAsyncValueCommand`
329-
- `IAsyncValueCommand : ICommand`
330326

331327
```csharp
332328
public AsyncCommand(Func<T, Task> execute,
333-
Func<object, bool> canExecute = null,
334-
Action<Exception> onException = null,
329+
Func<object, bool>? canExecute = null,
330+
Action<Exception>? onException = null,
335331
bool continueOnCapturedContext = false)
336332
```
337333

338334
```csharp
339335
public AsyncCommand(Func<Task> execute,
340-
Func<object, bool> canExecute = null,
341-
Action<Exception> onException = null,
336+
Func<object, bool>? canExecute = null,
337+
Action<Exception>? onException = null,
342338
bool continueOnCapturedContext = false)
343339
```
344340

@@ -413,6 +409,110 @@ public class ExampleClass
413409
}
414410
```
415411

412+
### `AsyncValueCommand`
413+
414+
Allows for `ValueTask` to safely be used asynchronously with `ICommand`.
415+
416+
New to `ValueTask`? Check out this great write-up, [Understanding the Whys, Whats, and Whens of ValueTask
417+
](https://blogs.msdn.microsoft.com/dotnet/2018/11/07/understanding-the-whys-whats-and-whens-of-valuetask?WT.mc_id=asyncawaitbestpractices-github-bramin).
418+
419+
- `AsyncValueCommand<T> : IAsyncValueCommand<T>`
420+
- `IAsyncValueCommand<T> : ICommand`
421+
- `AsyncValueCommand : IAsyncValueCommand`
422+
- `IAsyncValueCommand : ICommand`
423+
424+
```csharp
425+
public AsyncValueCommand(Func<T, ValueTask> execute,
426+
Func<object, bool>? canExecute = null,
427+
Action<Exception>? onException = null,
428+
bool continueOnCapturedContext = false)
429+
```
430+
431+
```csharp
432+
public AsyncValueCommand(Func<ValueTask> execute,
433+
Func<object, bool>? canExecute = null,
434+
Action<Exception>? onException = null,
435+
bool continueOnCapturedContext = false)
436+
```
437+
438+
```csharp
439+
public class ExampleClass
440+
{
441+
bool _isBusy;
442+
443+
public ExampleClass()
444+
{
445+
ExampleValueTaskCommand = new AsyncValueCommand(ExampleValueTaskMethod);
446+
ExampleValueTaskIntCommand = new AsyncValueCommand<int>(ExampleValueTaskMethodWithIntParameter);
447+
ExampleValueTaskExceptionCommand = new AsyncValueCommand(ExampleValueTaskMethodWithException, onException: ex => Debug.WriteLine(ex.ToString()));
448+
ExampleValueTaskCommandWithCanExecuteChanged = new AsyncValueCommand(ExampleValueTaskMethod, _ => !IsBusy);
449+
ExampleValueTaskCommandReturningToTheCallingThread = new AsyncValueCommand(ExampleValueTaskMethod, continueOnCapturedContext: true);
450+
}
451+
452+
public IAsyncValueCommand ExampleValueTaskCommand { get; }
453+
public IAsyncValueCommand<int> ExampleValueTaskIntCommand { get; }
454+
public IAsyncValueCommand ExampleValueTaskExceptionCommand { get; }
455+
public IAsyncValueCommand ExampleValueTaskCommandWithCanExecuteChanged { get; }
456+
public IAsyncValueCommand ExampleValueTaskCommandReturningToTheCallingThread { get; }
457+
458+
public bool IsBusy
459+
{
460+
get => _isBusy;
461+
set
462+
{
463+
if (_isBusy != value)
464+
{
465+
_isBusy = value;
466+
ExampleValueTaskCommandWithCanExecuteChanged.RaiseCanExecuteChanged();
467+
}
468+
}
469+
}
470+
471+
async ValueTask ExampleValueTaskMethod()
472+
{
473+
var random = new Random();
474+
if (random.Next(10) > 9)
475+
await Task.Delay(1000);
476+
}
477+
478+
async ValueTask ExampleValueTaskMethodWithIntParameter(int parameter)
479+
{
480+
var random = new Random();
481+
if (random.Next(10) > 9)
482+
await Task.Delay(parameter);
483+
}
484+
485+
async ValueTask ExampleValueTaskMethodWithException()
486+
{
487+
var random = new Random();
488+
if (random.Next(10) > 9)
489+
await Task.Delay(1000);
490+
491+
throw new Exception();
492+
}
493+
494+
void ExecuteCommands()
495+
{
496+
_isBusy = true;
497+
498+
try
499+
{
500+
ExampleValueTaskCommand.Execute(null);
501+
ExampleValueTaskIntCommand.Execute(1000);
502+
ExampleValueTaskExceptionCommand.Execute(null);
503+
ExampleValueTaskCommandReturningToTheCallingThread.Execute(null);
504+
505+
if (ExampleValueTaskCommandWithCanExecuteChanged.CanExecute(null))
506+
ExampleValueTaskCommandWithCanExecuteChanged.Execute(null);
507+
}
508+
finally
509+
{
510+
_isBusy = false;
511+
}
512+
}
513+
}
514+
```
515+
416516
## Learn More
417517
- [Removing Async Void](https://johnthiriet.com/removing-async-void/)
418518
- [MVVM Going Async with Async Command](https://johnthiriet.com/mvvm-going-async-with-async-command/)

0 commit comments

Comments
 (0)