-2

I want Method2 to execute only after an async method returns. Is there a way to do that ?

public class ViewModelBase
{

    public ICommand ClickCommand {get; private set;}

     public ViewModelBase()
     { 
         ClickCommand= new DelegateCommand<object>(myAsyncMethod);
     }

    private async void myAsyncMethod(object Param)
    {
        await Task.Run(()=> 
               {
                 // Do stuff
               });
    }


  private void Method2()
  {
    //Do things
  }

}

WPF

<ig:XamBusyIndicator DataContext="{Binding vm}" IsBusy="{Binding IsRunning}">
    <ContentControl Content="{Binding DisplayType}">
        <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate></DataTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                   <Trigger Property="Content"
                             Value="One">
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <igDP:XamDataGrid 
                                        DataContext="{Binding DataContext}"
                                        DataSource="{Binding UnDustedCollection}"></igDP:XamDataGrid>
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <Trigger Property="Content"
                             Value="Two">
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <igDP:XamDataGrid 
                                        DataContext="{Binding DataContext}"
                                        DataSource="{Binding DustedCollection}"></igDP:XamDataGrid>     
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</ig:XamBusyIndicator>
Sami
  • 89
  • 10
  • 3
    you can just call it after `await Task.Run` line and check if the Task was successful, if that's what you meant – Ehsan Sajjad Nov 06 '17 at 17:30
  • 3
    Put it after the `await` call? – nvoigt Nov 06 '17 at 17:30
  • @EhsanSajjad The reason I want to do that: I have a datagrid that will not appear in VisualTree until the async method returns. Method2 is using the Visual Tree and need to see that datagrid. – Sami Nov 06 '17 at 17:32
  • 1
    so then just call after the `await` line, it will make sure that `Method2` is called after the `async` method completes – Ehsan Sajjad Nov 06 '17 at 17:34
  • @EhsanSajjad Please see update code. The XamBusyIndicator is the issue. The grid will not appear in the visual tree until the async method returns. – Sami Nov 06 '17 at 17:39
  • @Sami `async void` is just a trick to make "async" methods compatible with events. `myAsyncMethod` will return to the caller before it awaits it's task – Sam I am says Reinstate Monica Nov 06 '17 at 17:39
  • @SamIam Do you have any suggestions ? – Sami Nov 06 '17 at 17:42
  • And if you need some other element to be present before `Method2` runs, then you should probably key `Method2` off of some event of that element(in this case, that datagrid you mentioned) – Sam I am says Reinstate Monica Nov 06 '17 at 17:42
  • @Sami did you actually try placing the call after `await Task.Run`? if you did what happened? What should have happened? – Sam I am says Reinstate Monica Nov 06 '17 at 17:43
  • [Possibly helpful answer from a different topic](https://stackoverflow.com/questions/46848666/how-does-a-toolbar-button-know-to-await/46857643#46857643), you need to use async aware ICommand. Nito.Mvvm.Async provides that. You can then change your `async void` to a `async Task` then have your busy indicator show while the task is running by binding to `ClickCommand.IsExecuting` – Scott Chamberlain Nov 06 '17 at 17:44
  • @SamIam I placed the Method2() call after the await Task.Run. What happens is that Method2 does not find the XamDataGrid in the visual tree in order to export it to a file – Sami Nov 06 '17 at 17:56
  • The visual tree has nothing to do with async/await...what are you doing in the Task? – mm8 Nov 07 '17 at 13:25

1 Answers1

0

Just call your method after await or wrap myAsyncMethod in another async method and do it similarly there.

private async void myAsyncMethod(object Param)
{
    await Task.Run(()=> 
           {
             // Do stuff. Not going to have safe access to UI elements
           });

    // await completed asynchronously.
    Method2(); // this method will have safe access to UI elements 
}

Note that if you need tighter integration with button state - How does a toolbar button know to await? has some ideas (as suggested by  Scott Chamberlain).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • This is exactly what I did, but it did not work for me because the XamDataGrid will not appear in the Visual Tree until the async method returns. – Sami Nov 06 '17 at 18:27
  • @Sami this is not what the question is asking about right now - please read [MCVE] guidance and make sure to either [edit] question to actually ask about what you need. – Alexei Levenkov Nov 06 '17 at 18:41