Skip to content

Commit

Permalink
Merge pull request #371 from nventive/dev/jpl/async-void
Browse files Browse the repository at this point in the history
fix: Resolve async void usages
  • Loading branch information
jeanplevesque authored Oct 30, 2023
2 parents 47bc3e5 + e1bbf54 commit 7f85afe
Show file tree
Hide file tree
Showing 16 changed files with 35 additions and 284 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,12 @@ dotnet_diagnostic.SA1210.severity = suggestion
dotnet_diagnostic.CA1308.severity = none
# CS1587: XML comment is not placed on a valid language element
dotnet_diagnostic.CS1587.severity = none

# VSTHRD110: This one is bugged: https://github.com/microsoft/vs-threading/issues/899
dotnet_diagnostic.VSTHRD110.severity = none
# VSTHRD200: Use `Async` naming convention
dotnet_diagnostic.VSTHRD200.severity = none
# VSTHRD100: Avoid async void methods
dotnet_diagnostic.VSTHRD100.severity = error
# VSTHRD101: Avoid unsupported async delegates
dotnet_diagnostic.VSTHRD101.severity = error
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
Prefix your items with `(Template)` if the change is about the template and not the resulting application.

## 2.1.X
- Replace local `DispatcherQueue` extension methods with the ones from the WinUI and Uno.WinUI Community Toolkit.
- Add `Microsoft.VisualStudio.Threading.Analyzers` to check for async void usages and fix async void usages.
- Enable `TreatWarningsAsErrors` for the Access, Business, and Presentation projects.
- Update analyzers packages and severity of rules.

Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<!-- Microsoft.VisualStudio.Threading.Analyzers has the async void analyzers. -->
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.5.22" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<PackageReference Include="Nventive.View.Uno.WinUI" Version="0.5.0-dev.62" />
<PackageReference Include="Reactive.Annex.Uno.WinUI" Version="0.6.0-dev.50" />
<PackageReference Include="ReviewService.NativePrompters" Version="1.0.0" />
<PackageReference Include="Uno.CommunityToolkit.WinUI" Version="7.1.100" />
<PackageReference Include="Uno.Material.WinUI" Version="3.0.40" />
<PackageReference Include="Uno.Microsoft.Xaml.Behaviors.Interactivity.WinUI" Version="2.3.1-uno.2" />
<PackageReference Include="Uno.Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.3.1-uno.2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public static class ObservableExtensions2
/// <param name="delay">Time delay</param>
/// <param name="scheduler">Scheduler</param>
/// <returns>Output observable</returns>
[SuppressMessage("nventive.Globalization", "NV2005:NV2005 - Simple cyclomatic complexity​​", Justification = "Imported code")]
[SuppressMessage("nventive.Reliability", "NV0016:NV0016 - Do not create an async void lambda expression", Justification = "Imported code")]
[SuppressMessage("Usage", "VSTHRD101:Avoid unsupported async delegates", Justification = "Imported code")]
public static IObservable<T> ThrottleOrImmediate<T>(this IObservable<T> source, TimeSpan delay, IScheduler scheduler)
{
// Throttle behavior:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ public class DadJokesFiltersPageViewModel : ViewModel
{
public DadJokesFiltersPageViewModel()
{
var pt = this.GetService<IDadJokesService>().GetAndObservePostTypeFilter();
var postType = GetPostType(pt);

PostTypeFilter = postType.Result;

async Task<PostTypes> GetPostType(ReplaySubject<PostTypes> ptArg)
{
return await ptArg.FirstAsync();
}
}

public IDynamicCommand HandleCheck => this.GetCommand((string pt) =>
Expand All @@ -40,7 +31,7 @@ async Task<PostTypes> GetPostType(ReplaySubject<PostTypes> ptArg)

public PostTypes PostTypeFilter
{
get => this.Get<PostTypes>(initialValue: PostTypes.Hot);
get => this.GetFromTask<PostTypes>(ct => this.GetService<IDadJokesService>().GetAndObservePostTypeFilter().FirstAsync(ct), initialValue: PostTypes.Hot);
set => this.Set(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public string SelectedKey
ConfigurationValue = this.GetService<IConfiguration>()[value];

// Erase the selection from the ComboBox because we put it in the TextBox.
Task.Run(() => RaisePropertyChanged(nameof(SelectedKey)));
_ = Task.Run(() => RaisePropertyChanged(nameof(SelectedKey)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
<Compile Include="$(MSBuildThisFileDirectory)Framework\Version\VersionProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\AppBarBackButton.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\DependencyObjectExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\DispatcherQueueExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\FrameworkElementExtension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ObservableExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Shell.xaml.cs">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Text;
using CommunityToolkit.WinUI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand Down Expand Up @@ -196,7 +197,7 @@ private static void FormatText(TextBox textbox, string textFormat)
return;
}

_ = textbox.DispatcherQueue.RunAsync(DispatcherQueuePriority.Normal, () =>
_ = textbox.DispatcherQueue.EnqueueAsync(() =>
{
textbox.Text = formattedText;
textbox.SelectionStart = selectionStart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Windows.Input;
using Chinook.DynamicMvvm;
using Chinook.SectionsNavigation;
using CommunityToolkit.WinUI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
Expand Down Expand Up @@ -77,7 +78,7 @@ private IDisposable ObserveBackButtonVisibility()
void OnStateChanged(bool canNavigateBackOrCloseModal)
{
var dispatcherQueue = ServiceProvider.GetRequiredService<DispatcherQueue>();
_ = dispatcherQueue.RunAsync(DispatcherQueuePriority.Normal, UpdateBackButtonUI);
_ = dispatcherQueue.EnqueueAsync(UpdateBackButtonUI);

void UpdateBackButtonUI() // Runs on UI thread.
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using CommunityToolkit.WinUI;

namespace ApplicationTemplate;

Expand Down Expand Up @@ -78,7 +79,7 @@ private void OnPropertyNamedChanged()

private void OnErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
_ = DispatcherQueue.RunAsync(DispatcherQueuePriority.Normal, ErrorsChangedUI);
_ = DispatcherQueue.EnqueueAsync(ErrorsChangedUI);

void ErrorsChangedUI()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.UI.Dispatching;
using CommunityToolkit.WinUI;
using Microsoft.UI.Dispatching;

namespace ApplicationTemplate;

Expand All @@ -13,7 +14,7 @@ public ExtendedSplashscreenController(DispatcherQueue dispatcherQueue)

public void Dismiss()
{
_ = _dispatcherQueue.RunAsync(DispatcherQueuePriority.Normal, DismissSplashScreen);
_ = _dispatcherQueue.EnqueueAsync(DismissSplashScreen);

void DismissSplashScreen() // Runs on UI thread.
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using CommunityToolkit.WinUI;
using Microsoft.UI.Dispatching;

namespace ApplicationTemplate;
Expand All @@ -15,37 +16,15 @@ public LauncherService(DispatcherQueue dispatcherQueue)

public async Task Launch(Uri uri)
{
var launchSucceeded = await DispatcherRunTaskAsync(DispatcherQueuePriority.Normal, async () => await Windows.System.Launcher.LaunchUriAsync(uri));
var launchSucceeded = await _dispatcherQueue.EnqueueAsync(InnerLaunch, DispatcherQueuePriority.Normal);
if (!launchSucceeded)
{
throw new LaunchFailedException($"Failed to launch URI: {uri}");
}
}

/// <summary>
/// This method allows for executing an async Task with result on the <see cref="DispatcherQueue"/>.
/// </summary>
/// <typeparam name="TResult">The <see cref="DispatcherQueue"/> result type.</typeparam>
/// <param name="dispatcherQueuePriority"><see cref="DispatcherQueuePriority"/>.</param>
/// <param name="asyncFunc">A function that will be execute on the <see cref="DispatcherQueue"/>.</param>
/// <returns><see cref="Task"/> of <typeparamref name="TResult"/>.</returns>
private async Task<TResult> DispatcherRunTaskAsync<TResult>(DispatcherQueuePriority dispatcherQueuePriority, Func<Task<TResult>> asyncFunc)
{
var completion = new TaskCompletionSource<TResult>();
await _dispatcherQueue.RunAsync(dispatcherQueuePriority, RunActionUI);
return await completion.Task;

async void RunActionUI()
async Task<bool> InnerLaunch()
{
try
{
var result = await asyncFunc();
completion.SetResult(result);
}
catch (Exception exception)
{
completion.SetException(new LaunchFailedException("An error occured while trying to launch an URI on the UI thread.", exception));
}
return await Windows.System.Launcher.LaunchUriAsync(uri);
}
}
}
Loading

0 comments on commit 7f85afe

Please sign in to comment.