Currently I'm using this code in order to get a file:
WebClient webClient = new WebClient();
webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(webClient_ProgressCompleted);
I've been taking a look on documentation in order to figure out how to turn this code out using Rx.
I've kicked off creating an Observable using FromEvent in order to watch out DownloadFileCompleted event.
Observable.FromEvent<?>(?, ?)
Nevertheless, I'm not able to figure how to fill these ?.
Could somebody get me an example?
Up to now, I've tried with:
Observable.FromEvent<AsyncCompletedEventArgs>(?1:addHandler, ?2:removeHandler).
Nevertheless, .net is requesting me that ?1:addHandler and ?2:removeHandler are Action<Action<AsyncCompletedEventArgs>> (what's that)?
These overloads are so tricky, I have to look them up every time. I've included some sample subscription code to get you started:
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);
EDIT:
Per @Enigmativity's suggestion, it is possible to do all this code in a functional style, which also handles cleaning up all the IDisposables. However, I don't find it as readable, and as such wouldn't recommend it:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With