c# - 使用 Rx 下载文件(响应式编程)

标签 c# .net system.reactive

目前我正在使用这段代码来获取文件:

WebClient webClient = new WebClient();
webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(webClient_ProgressCompleted);

我一直在查看文档以了解如何使用 Rx 生成此代码。

我已经开始创建 Observable使用 FromEvent为了提防DownloadFileCompleted事件。

Observable.FromEvent<?>(?, ?)

不过,我不知道如何填写这些 ? .

有人能给我举个例子吗?

到目前为止,我尝试过:

Observable.FromEvent<AsyncCompletedEventArgs>(?1:addHandler, ?2:removeHandler).

尽管如此,.net 要求我 ?1:addHandler?2:removeHandlerAction<Action<AsyncCompletedEventArgs>> (那是什么)?

最佳答案

这些重载是如此棘手,我不得不look them up every time .我提供了一些示例订阅代码来帮助您入门:

WebClient webClient = new WebClient();
var progressChangedObservable = Observable.FromEventPattern<DownloadProgressChangedEventHandler, DownloadProgressChangedEventArgs>(
    h => webClient.DownloadProgressChanged += h,
    h => webClient.DownloadProgressChanged -= h
);

var downloadCompletedObservable = Observable.FromEventPattern<AsyncCompletedEventHandler, AsyncCompletedEventArgs>(
    h => webClient.DownloadFileCompleted += h,
    h => webClient.DownloadFileCompleted -= h
);

progressChangedObservable
    .Select(ep => ep.EventArgs)
    .Subscribe(dpcea =>  Console.WriteLine($"{dpcea.ProgressPercentage}% complete. {dpcea.BytesReceived} bytes received. {dpcea.TotalBytesToReceive} bytes to receive."));

downloadCompletedObservable
    .Select(ep => ep.EventArgs)
    .Subscribe(_ => Console.WriteLine("Download file complete."));

var dummyDownloadPath = @"C:\temp\temp.txt";
webClient.DownloadFileAsync(new Uri(@"http://google.com"), dummyDownloadPath);

编辑:

根据@Enigmativity 的建议,可以以函数式风格执行所有这些代码,它还负责清理所有 IDisposable。但是,我觉得它可读性差,因此不推荐它:

    Observable.Using(() => 
    {
        var webClient = new WebClient();
        webClient.Headers.Add("User-Agent: Other");
        return webClient;
    }, webClient =>
    Observable.Using(() => 
        Observable.FromEventPattern<DownloadProgressChangedEventHandler, DownloadProgressChangedEventArgs>(
                h => webClient.DownloadProgressChanged += h,
                h => webClient.DownloadProgressChanged -= h
            )
            .Select(ep => ep.EventArgs)
            .Subscribe(dpcea => Console.WriteLine($"{dpcea.ProgressPercentage}% complete. {dpcea.BytesReceived} bytes received. {dpcea.TotalBytesToReceive} bytes to receive.")),
        sub1 => Observable.Using(() =>
            Observable.FromEventPattern<AsyncCompletedEventHandler, AsyncCompletedEventArgs>(
                    h => webClient.DownloadFileCompleted += h,
                    h => webClient.DownloadFileCompleted -= h
                )
                .Select(ep => ep.EventArgs)
                .Subscribe(_ => Console.WriteLine("Download file complete.")),
            sub2 => webClient.DownloadFileTaskAsync(new Uri(@"http://google.com"), @"C:\temp\temp.txt").ToObservable()
        )
    )
)
    .Subscribe(_ => {} ); //Subscription required to trigger nested observables

关于c# - 使用 Rx 下载文件(响应式编程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41552052/

相关文章:

c# - 如何在只有 setter 的接口(interface)上模拟委托(delegate)的提升?

c# - 尝试将字段添加到表中时出现 Entity Framework 错误 3004

c# - 如何像 JSON.stringify() 那样在 C# 中对 json 进行字符串化/规范化

.net - 是否可以在 .NET 中在运行时修改方法体?

c# - 在不重新评估序列的情况下获取 IObservable 中的前一个元素

c# - LINQ 多个关键字搜索到 PagedList

c# - 用 C# 编写全局自定义事件

.NET企业应用平台(同JBoss转Java)

c# - 在 .NET 的 Reactive Extensions 中使用 Observable.FromEventPattern 时如何避免任何阻塞?

c# - 使用 Reactive Extensions 的事件聚合器问题