0

I've been getting the CS4014 warning in Visual Studio developing UWP apps, and can't figure out what to do with them. I know there's a way to suppress them in VS, but I don't want to suppress all CS4014 warnings altogether.

Warning CS4014 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

The reason it's troubling is it is showing up on *.g.cs files which are generated automatically by VS, I assume.

Carlo Mendoza
  • 765
  • 6
  • 24

1 Answers1

0

Note: If there's someone more knoweledgeable who can tell me why this isn't good, please do.

After some time trying to figure this out, I realized that the *.g.cs files are generated from my XAML. The warning shows up for events bound to methods in my ViewModel that are not synchronous(?)

Example PageExample.xaml.g.cs:

case 15: // Views\PageExample.xaml line 72
    this.obj15 = (global::Windows.UI.Xaml.Controls.ToggleMenuFlyoutItem)target;
    this.obj15Click = (global::System.Object p0, global::Windows.UI.Xaml.RoutedEventArgs p1) =>
    {
        //Warning CS4014 because of line below. 
        //I can add await before this line all I want, 
        //but the file gets regenerated anyway.
        this.dataRoot.ViewModel.Refresh();
    };
    ((global::Windows.UI.Xaml.Controls.ToggleMenuFlyoutItem)target).Click += obj15Click;
    this.bindingsTracking.RegisterTwoWayListener_15(this.obj15);
    break;

Example XAML PageExample.xaml:

<ToggleMenuFlyoutItem Text="Toggle" Click="{x:Bind ViewModel.Refresh}" />

Example ViewModel.cs:

//Warning CS4014 on the .g.cs file because this is async
public async Task Refresh()
{
      //code you actually want
}

I've tried just changing to async void on the Refresh method but it seems to have an effect that caused timing issues in my case. This is what seems to work. Ugly, but seems to address the warning.

ViewModel.cs:

//No more warning CS4014 since it's async void
public async void Refresh()
{
      await RefreshAsync();
}
public async Task RefreshAsync()
{
      //code you actually want
}

Per Jon's comment, I suppose, this reasonable:

//no need to be async void
public void Refresh()
{
    //discard
    _ = RefreshAsync();
}
Carlo Mendoza
  • 765
  • 6
  • 24
  • 2
    Fundamentally it looks like the generated code expects `Refresh()` to be synchronous. Are you able to write synchronous refresh code instead, and call your *asynchronous* refresh method `RefreshAsync`? – Jon Skeet Apr 20 '19 at 07:54
  • Hi Jon! Makes sense. Edited to hopefully line up with what you just said. – Carlo Mendoza Apr 20 '19 at 08:10
  • No, that's still refreshing asynchronously. You either need to be able to refresh synchronously, or somehow change the generated code (e.g. via a script that does the right thing after generation, as a hacky option). – Jon Skeet Apr 20 '19 at 08:13
  • Hmm. `RefreshAsync` is littered with `await` lines that, to me, seems harder to convert so `RefreshAsync` can be turned synchronous (moved over to `Refresh`). This is hacky, too. Right? – Carlo Mendoza Apr 20 '19 at 08:20
  • I'm afraid I don't see what you're proposing. If you really can't refresh synchronously, I think you're going to have to work out a way of changing the generated code. (I'm now unavailable for several hours, so won't be able to add any more comments.) – Jon Skeet Apr 20 '19 at 08:22