我正在为CRM创建一个silverlight应用程序,如下所示:
1- usercontrol 这是一个表单,其中填充了使用async / await从CRM检索到的数据
2- 打印按钮,用于创建该用户控件的实例并将其打印
我在执行序列中遇到问题导致Print按钮打印没有数据的用户控件,这意味着它在异步方法完成之前执行。
我的代码如下:
用户控制:
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
...
}
}
我的打印按钮:
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");
}
当我单击Print时,会创建一个新的ManagerContact用户控件实例,执行将遍历用户控件中的所有功能,直到到达该行
var response = await service.RetrieveMultiple(query);
然后返回打印按钮功能并继续打印页面。问题是它跳过了我用数据填充表单控件的其余函数,因此表单打印时没有数据。
我需要找到一种方法来强制执行以等待响应被返回,并且只有在它获得响应之后才会返回到主页以继续打印按钮。
答案 0 :(得分:3)
您的问题归因于async void
。作为一般准则,请避免async void
;它应该只用于事件处理程序。有关详细信息,请参阅我的MSDN article on asynchronous best practices。
因此,您的getData
方法应如下所示:
private async Task getDataAsync(string contactid)
无论调用它应该await
它返回Task
,这意味着 函数也需要async
并返回Task
或者Task<T>
等等。
最终,您发现您的构造函数不能是async
,因此我建议您创建一个异步工厂方法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;
}
}
然后你可以这样使用:
private async void PrintOrExport(object sender, RoutedEventArgs e)
{
ManagerContact mymanager = await Common.ManagerContact.CreateAsync(mycontactid);
...
}