【发布时间】:2015-05-04 20:23:44
【问题描述】:
我有一个类库(除其他外),它充当 Web API 的外部客户端库的包装器。
我的(简化的)代码在这里接受一个查询字符串,生成一个ReportUtilities 对象,使用它来下载报告,然后将报告字符串返回给调用者:
public string GetXmlReport(string queryString)
{
ReportUtilities reportUtil = new ReportUtilities(_user,queryString,"XML");
byte[] data = reportUtil.GetResponse().Download();
return Encoding.UTF8.GetString(data);
}
问题在于此方法使用同步方法从 Web 服务下载数据。我想通过在我的类中添加一个GetXmlReportAsync() 方法来使这个在我的库中异步可用。
现在,如果 ReportUtilities 类提供了一个返回 Task<byte[]> 的 GenerateAndDownloadAsync() 方法,这将是直截了当的,但不幸的是它没有,它在外部库中,所以我坚持使用它提供的内容。
ReportUtilities 类确实有一个 GetResponseAsync() 方法返回 void 并为 OnReadyCallback 方法和 OnReadyCallback OnReady{get;set;} 属性提供委托。
我应该补充一点,.GetResponse() 返回一个 ReportResponse 对象,它确实有一个 DownloadAsync() 方法,但同样,它返回的是 void 而不是 Task<byte[]>。同样ReportResponse 带有OnDownloadSuccessCallback 委托和OnDownloadSuccessCallback OnDownloadSuccess { get; set; } 属性。
就好像外部库作者在“滚动他们自己的”异步 API 而不是使用 C# 中内置的 API?
我的问题是:如何在我的类中实现GetXmlReportAsync() 方法以最有效地利用客户端库中的异步函数?
显然我可以这样做:
public async Task<string> GetXmlReportAsync(string queryString)
{
ReportUtilities reportUtil = new ReportUtilities(_user,queryString,"XML");
byte[] data = await Task.Run(() => { return reportUtil.GetResponse().Download(); });
return Encoding.UTF8.GetString(data);
}
但随后线程被 2 个对外部库的同步输入/输出方法调用所束缚:.GetResponse() 和 .Download() 这肯定不是最佳的?
另外,我可以想象这样一种情况,我只是在我自己的外部库中公开了一个类似的 API,而客户端必须在报告准备好时提供回调,但我更愿意将其包装成更熟悉的异步/await 样式 API。
我是想在圆孔中安装一个方形钉,还是我错过了一种将其包装到异步/等待样式 API 中的巧妙方法?
【问题讨论】:
-
您的问题是“如何等待事件?”?那个已经回答了,应该可以帮助你。
标签: c# asynchronous async-await