How to force execution to stop till asynchronous function is fully executed?

空扰寡人 提交于 2020-01-03 05:22:10

问题


I'm creating a silverlight application for CRM as follow:

1- A usercontrol which is a form is filled with data retrieved from the CRM using async/await

2- A Print button that creates an instance of that usercontrol and prints it

I have a problem in the sequence of execution that causes the Print button to print the usercontrol with no data, meaning, it's executed before the async method finishes.

My code is as follows:

User control:

   Public partial class ManagerContact : UserControl
     // constructor and functions
     ... 
   async private  void getData(string contactid)
    {
        // get some details of the contact 

            QueryExpression query = new QueryExpression();
            query.EntityName = "contact";
            ColumnSet cset = new ColumnSet();
            cset.Columns = new System.Collections.ObjectModel.ObservableCollection<string>(new String[] { "emailaddress1","fullname"  });  
            query.ColumnSet = cset;


            IOrganizationService service = SilverlightUtility.GetSoapService();
            var response = await service.RetrieveMultiple(query);

           /// PROBLEM HERE

            List<contacts> mycontactlist= new List<contacts>();
           // a function to fill the controls in the form with the retrieved data
            ...
         }
     }

My Print Button:

   private  void PrintOrExport(object sender, RoutedEventArgs e)
    {
        PrintDocument document = new PrintDocument();

       ManagerContact mymanager= new Common.ManagerContact(mycontactid);

             document.PrintPage += (s, args) =>
            {
              // code here to prepare the pagevisual
            }
       document.Print("title");
     } 

When I click Print, a new instance of ManagerContact user control is created and execution goes through all the functions in the user control till it reaches the line

   var response = await service.RetrieveMultiple(query);

and then it returns back to the Print Button function and proceeds to print the page. The problem is it skips the rest of the functions where I fill the form controls with the data and so the form is printed with no data.

I need to find a way to force execution to wait for the response to be returned and only after it gets teh response execution would go back to the main page for the rest of the print button.


回答1:


Your problem is due to async void. As a general guideline, avoid async void; it should only be used for event handlers. For more information, see my MSDN article on asynchronous best practices.

So, your getData method should look like this:

private async Task getDataAsync(string contactid)

And whatever calls it should await the Task it returns, which means that function also needs to be async and return Task or Task<T>, etc.

Eventually, you'll find that your constructor cannot be async, so I recommend you create an asynchronous factory method as I describe on my blog:

class ManagerContact
{
  private ManagerContact(int contactId)
  {
    ...
  }

  private async Task InitializeAsync()
  {
    await getDataAsync();
    ...
  }

  public static async Task<ManagerContact> CreateAsync(int id)
  {
    var result = new ManagerContact(id);
    await result.InitializeAsync();
    return result;
  }
}

Which you can then use like this:

private async void PrintOrExport(object sender, RoutedEventArgs e)
{
  ManagerContact mymanager = await Common.ManagerContact.CreateAsync(mycontactid);
  ...
}


来源:https://stackoverflow.com/questions/22808475/how-to-force-execution-to-stop-till-asynchronous-function-is-fully-executed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!