Problem: I inherited WebClient
in ExtendedWebClient
where I override the WebRequest
's timeout property in the GetWebRequest
method. If I set it to 100ms, or even 20ms, it always takes up to more than 30 seconds at least. Sometimes it seems to not get through at all.
Also, when the service (see code below) serving the images comes back online again, the code written in Rx / System.Reactive does not push images into the pictureBox anymore?
How can I get around this, what am I doing wrong? (See code below)
Test case: I have a WinForms test project set up for this, which is doing the following.
GetNextImageAsync
public async Task<Image> GetNextImageAsync() { Image image = default(Image); try { using (var webClient = new ExtendedWebClient()) { var data = await webClient.DownloadDataTaskAsync(new Uri("http://SOMEIPADDRESS/x/y/GetJpegImage.cgi")); image = ByteArrayToImage(data); return image; } } catch { return image; } }
ExtendedWebClient
private class ExtendedWebClient : WebClient { protected override WebRequest GetWebRequest(Uri address) { var webRequest = base.GetWebRequest(address); webRequest.Timeout = 100; return webRequest; } }
3.1 Presentation code (using Rx)
Note: It has actually never reached the "else" statement in the pictures.Subscribe()
body.
var pictures = Observable
.FromAsync<Image>(GetNextImageAsync)
.Throttle(TimeSpan.FromSeconds(.5))
.Repeat()
;
pictures.Subscribe(img => {
if (img != null) {
pictureBox1.Image = img;
} else {
if (pictureBox1.Created && this.Created) {
using (var g = pictureBox1.CreateGraphics()) {
g.DrawString("[-]", new Font("Verdana", 8), Brushes.Red, new PointF(8, 8));
}
}
}
});
3.2 Presentation code (using Task.Run)
Note 1: Here the "else" body is getting called, though WebClient still takes longer than expected to timeout....
Note 2: I don't want to use this method, because this way I can't "Throttle" the image stream, I'm not able to get them in proper order, and do other stuff with my stream of images... But this is just example code of it working...
Task.Run(() => {
while (true) {
GetNextImageAsync().ContinueWith(img => {
if(img.Result != null) {
pictureBox1.Image = img.Result;
} else {
if (pictureBox1.Created && this.Created) {
using (var g = pictureBox1.CreateGraphics()) {
g.DrawString("[-]", new Font("Verdana", 8), Brushes.Red, new PointF(8, 8));
}
}
}
});
}
});
As reference, the code to tranfser the
byte[]
to theImage
object.public Image ByteArrayToImage(byte[] byteArrayIn) { using(var memoryStream = new MemoryStream(byteArrayIn)){ Image returnImage = Image.FromStream(memoryStream); return returnImage; } }