DownloadStringAsync 和其他事件方法与 .NET 4.0 中的 TPL 配合得非常好(检查 EAP 和 TPL)。通常,TPL 确实通过 TaskCompletionSource 支持事件异步编程。通过 Task.FromAsync 方法支持 Begin/EndXXX 模型 (APM)。您可以找到TPL 和传统 .NET 异步编程的详细说明。
ParallelExtensionExtras库有一组 WebClient 扩展方法,例如 DownloadStringTask,它们返回一个任务,该任务在适当的事件被触发时完成。
以下代码将创建一个任务,该任务将在下载完成时完成:
public Task<string> DownloadStringTask(WebClient client,Uri uri)
{
var tcs = new TaskCompletionSource<string>();
client.DownloadStringCompleted += (o, a) => tcs.SetResult(a.Result);
client.DownloadStringAsync(uri);
return tcs.Task;
}
至于更新 UI,您可以轻松地使用 DownloadProgressChanged 事件提供反馈,例如:
using (var client = new WebClient())
{
client.DownloadProgressChanged += (o, a) => Console.WriteLine("{0}",a.ProgressPercentage);
var task = DownloadStringTask(client,new Uri("http://www.stackoverflow.com"));
var write=task.ContinueWith(t => Console.WriteLine("Got {0} chars", t.Result.Length));
write.Wait();
Console.ReadKey();
}
如果您使用数据绑定向进度条提供进度值,则只需更新进度值属性即可。如果您直接更新进度条(不是一个好主意),您将不得不使用进度条的调度程序来编组对 UI 线程的调用,例如。像这样
void UpdateProgress(int percent)
{
if (progressBar1.CheckAccess())
progressBar1.Value = percent;
else
{
progressBar1.Dispatcher.Invoke(new Action(()=>UpdateProgress(percent)));
}
}
....
client.DownloadProgressChanged += (o, a) => UpdateProgress(a.ProgressPercentage);