gpt4 book ai didi

c# - 使用 TAP 的 WebClient 进度报告

转载 作者:太空宇宙 更新时间:2023-11-03 21:14:35 26 4
gpt4 key购买 nike

我想知道是否有一种方法可以在不使用 EAP(基于事件的异步模式)的情况下报告 WebClient 进度。旧方法(使用 EAP)是:

var client = new WebClient();
client.DownloadProgressChanged += (s,e) => { //progress reporting }
client.DownloadFileCompleted += (s,e) => { Console.Write("download finished" }
client.DownloadFileAsync(file);

对于 async/await 这可以写成:

var client = new WebClient();
client.DownloadProgressChanged += (s,e) => { //progress reporting }
await client.DownloadFileTaskAsync(file);
Console.Write("downlaod finished");

但在第二个示例中,我同时使用了 EAP 和 TAP(基于任务的异步模式)。混合两种异步模式不是一种不好的做法吗?

有没有一种方法可以在不使用 EAP 的情况下实现同样的效果?我已经阅读了有关 IProgress 接口(interface)的信息,但我认为没有办法使用它来报告 WebClient 进度。

最佳答案

坏消息是答案是NO!

好消息是任何 EAP API 都可以转换为 TAP API。

试试这个:

public static class WebClientExtensios
{
public static async Task DownloadFileTaskAsync(
this WebClient webClient,
Uri address,
string fileName,
IProgress<Tuple<long, int, long>> progress)
{
// Create the task to be returned
var tcs = new TaskCompletionSource<object>(address);

// Setup the callback event handler handlers
AsyncCompletedEventHandler completedHandler = (cs, ce) =>
{
if (ce.UserState == tcs)
{
if (ce.Error != null) tcs.TrySetException(ce.Error);
else if (ce.Cancelled) tcs.TrySetCanceled();
else tcs.TrySetResult(null);
}
};

DownloadProgressChangedEventHandler progressChangedHandler = (ps, pe) =>
{
if (pe.UserState == tcs)
{
progress.Report(
Tuple.Create(
pe.BytesReceived,
pe.ProgressPercentage,
pe.TotalBytesToReceive));
}
};

try
{
webClient.DownloadFileCompleted += completedHandler;
webClient.DownloadProgressChanged += progressChangedHandler;

webClient.DownloadFileAsync(address, fileName, tcs);

await tcs.Task;
}
finally
{
webClient.DownloadFileCompleted -= completedHandler;
webClient.DownloadProgressChanged -= progressChangedHandler;
}
}
}

然后像这样使用它:

void Main()
{
var webClient = new WebClient();

webClient.DownloadFileTaskAsync(
new Uri("http://feeds.paulomorgado.net/paulomorgado/blogs/en"),
@"c:\temp\feed.xml",
new Progress<Tuple<long, int, long>>(t =>
{
Console.WriteLine($@"
Bytes received: {t.Item1,25:#,###}
Progress percentage: {t.Item2,25:#,###}
Total bytes to receive: {t.Item3,25:#,###}");
})).Wait();
}

关于c# - 使用 TAP 的 WebClient 进度报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35281024/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com