如何等待webclient OpenReadAsync完成

我在Windows Phone 8.1应用程序中使用WebClient从Internet下载一些东西。 下面是我在我的应用程序中使用的示例代码 – 我在下面调用方法,但我的webclient没有等待完成读取操作并在OpenReadAsync调用后立即返回。

我怎样才能确保我的方法返回操作必须等到OpenReadCompleted事件完成后? 我见过多个类似的问题,但找不到解决方案。

MyCustomObject externalObj; // my custom object private static void CheckNetworkFile() { try { WebClient webClient = new WebClient(); webClient.OpenReadCompleted += (s, e) => { externalObj = myReadWebclientResponse(e.Result); // my custom method to read the response }; webClient.OpenReadAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute)); } catch (Exception) { externalObj = null; } } 

我建议您使用WebClient.OpenReadTaskAsync ,并结合使用.NET 4.5中引入的async/await关键字。 您需要将async关键字添加到您的方法,使其返回一个Task ,并建议使用Async后缀结束您的方法:

 MyCustomObject externalObj; private static async Task CheckNetworkFileAsync() { try { WebClient webClient = new WebClient(); Stream stream = await webClient.OpenReadTaskAsync(new Uri("http://externalURl.com/sample.xml", UriKind.Absolute)); externalObj = myReadWebclientResponse(stream); } catch (Exception) { externalObj = null; } } 

编辑:

如你所说, WebClient.OpenReadTaskAsync不适用于WP8.1,所以让我们创建一个扩展方法,它将是:

 public static class WebClientExtensions { public static Task OpenReadTaskAsync(this WebClient client, Uri uri) { var tcs = new TaskCompletionSource(); OpenReadCompletedEventHandler openReadEventHandler = null; openReadEventHandler = (sender, args) => { try { tcs.SetResult(args.Result); } catch (Exception e) { tcs.SetException(e); } }; client.OpenReadCompleted += openReadEventHandler; client.OpenReadAsync(uri); return tcs.Task; } } 

现在,您可以在WebClient上使用它。

您可以在async-await wiki中找到很棒的阅读材料,只需在搜索栏中按该标签过滤即可。

我希望这不是太偏离主题,但正在研究这个问题的其他人可能想知道上面的代码示例也可以用于Silverlight中的WCF调用。 请务必先添加Microsoft.Bcl.Async NuGet包。 这是一个WCF代码示例:

  public static async Task AuthenticateAsync(string userName, string password) { var dataAccessServiceClient = new DataAccessServiceClient("DataAccessService"); var taskCompletionSource = new TaskCompletionSource(); EventHandler completedHandler = null; completedHandler = (s, args) => { try { taskCompletionSource.SetResult(args.Result); } catch (Exception e) { taskCompletionSource.SetException(e); } }; dataAccessServiceClient.AuthenticateCompleted += completedHandler; dataAccessServiceClient.AuthenticateAsync(userName, password); return await taskCompletionSource.Task; } 

它可以像这样调用:

 var result = await AuthenticateAsync(username, password);