How to handle continous GET requests? - c#

I am working on a little Windows Form Application, that shows me the streams of several IP Cameras (from different companies) in my Network and also allows me to move the Cameras (left,right,up,down,zoom). This is realised with AFORGE.net MJPEG Streams and the camera movements through firing get requests.
Problem: I have one camera that doesn't move in steps (after each click on 'up' for example) but it moves continuously. It only stops when I send another request with the parameter 'stop'.
GET Request to Move Right:
http://192.XXX.XX.XXX:XXXX/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&-act=right&-speed=63
GET Request to Stop the movement:
http://192.XXX.XX.XXX:XXXX/web/cgi-bin/hi3510/ptzctrl.cgi?-step=0&- act=stop&-speed=63
Function I use for the other Cameras:
private void move_right()
{
string url = 'someURL';
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.GetResponse();
request.Abort();
}
I would like the camera to move right stepwise after clicking a button, but when firing the request to move right, my program just gets stuck.

Use the HttpClient object and create an asynchronous request, try something like (untested):
private async Task move_right()
{
var url = 'someURL';
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = new Uri(url),
Method = HttpMethod.Get,
};
var response = await client.SendAsync(request);
//Do something with your response
}
private async Task executeWebRequests()
{
//Usage - Await for result
await move_right();
//Execute asynchronously
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
move_right(); //Will create a new task and run asynchronously in the BG
}

I have a camera using the same url.
This thread is a few years old, but for anyone else interested, use step=1 to move stepwise.

Related

Run a async function without waiting for the response in c# webforms (fire and forget)

I have a button that makes a REST request to create a document:
private void Click(object sender, ActionBaseEventArgs e)
{
RequestQuotationDocument(quotation.Oid).ConfigureAwait(false);
}
private async System.Threading.Tasks.Task RequestQuotationDocument(int quotationId)
{
HttpClient client = new HttpClient();
var values = new
{
DocumentType = "Quotation",
Id = quotationId.ToString()
};
var content = new StringContent(JsonConvert.SerializeObject(values), System.Text.Encoding.UTF8,
"application/json");
await client.PostAsync(url, content);
}
However the page is still waiting for the response of the POST request. How do I make this truly async?
How do I make this truly async?
In ASP.NET, await yields to the thread pool, not the client.
If possible, I recommend changing the client so that a longer request is handled appropriately; e.g., calling this via JavaScript instead of a click handler, and updating the page when it completes.
If you really need to return early from an web request, then you should implement a basic distributed architecture. As described on my blog, this consists of two parts:
A durable queue of work.
A backend processor of that queue.

Forward multipart/x-mixed-replace live stream ASP.NET Core

I've an ASP.NET Core server that, upon client request, start fetching a stream from an AXIS camera and returns it to the client for displaying. If the http request to server is made directly by the browser by means of img src attribute, it works fine. But if I use HttpClient (which I need to do since I need CancellationToken), the httpClient.GetStreamAsync instruction get stuck and I cannot parse the returned data.
Server side Controller (take from here):
[ApiController]
[Route("[controller]")]
public class CameraSystemController : ControllerBase
{
private string _contentTypeStreaming = "multipart/x-mixed-replace;boundary=myboundary";
private HttpClient _httpClient = new HttpClient(new HttpClientHandler { Credentials = ...});
[HttpGet("getStream")]
public async Task<IActionResult> GetStream(CancellationToken token)
{
Stream stream = await _httpClient.GetStreamAsync("http://.../axis-cgi/mjpg/video.cgi?resolution=800x600&compression=50", token);
if (stream != null) {
FileStreamResult result = new FileStreamResult(stream, _contentTypeStreaming) {
EnableRangeProcessing = true
};
return result;
} else {
return new StatusCodeResult((int)HttpStatusCode.ServiceUnavailable);
}
}
}
Now, as I said, as long as I make the browser perform the http request by means of
// LiveCamera.razor
<img src="CameraSystem/getStream" onerror="#OnImgLoadingError" alt="">
Data acquired in live mode by the camera is correctly displayed in browser.
If instead I make the request in the client this way:
//LiveCamera.razor.cs
[Inject] public HttpClient Http { get; private set; }
private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
private async void StartStreamingRequest(object sender, ElapsedEventArgs e) {
Console.WriteLine("I'm about to request live stream");
Stream responseStream = await Http.GetStreamAsync("CameraSystem/getStream", _cancellationTokenSource.Token);
Console.WriteLine("Header found!");
string boundary = "myboundary";
for (MultipartReader streamReader = new MultipartReader(boundary, responseStream); ;) {
MultipartSection nextFrame = await streamReader.ReadNextSectionAsync(_cancellationTokenSource.Token);
DisplayOneFrameCallback(nextFrame.Body);
}
}
private void DisplayOneFrameCallback(Stream body)
{
StreamReader reader = new StreamReader(body);
string frameData = reader.ReadToEnd();
_imgSrc = "data:image/jpeg;base64," + frameData;
StateHasChanged();
}
In this seconds case the request is performed correctly (server-side I can see the code executed and from task manager I can see the bandwidth usage increasing) but the client got stuck on await instruction, and subsequent code is never executed. Now, in Microsoft documentation under GetStreamAsync it is possible to read
This operation will not block. The returned Task object will complete after the response headers are read. This method does not read nor buffer the response body.
so I would expect it not to block. Thus I suppose there could be a problem in the header I'm producing server-side, even though browser request works just fine.
Just out of curiosity, I've captured with Wireshark the data between the camera and the server. The header and the initial part of the body are like this:
..-...HTTP/1.0 200 OK..Cache-Control: no-cache..Pragma: no-cache..Expires: Thu, 01 Dec 1994 16:00:00 GMT..Connection: close..Content-Type: multipart/x-mixed-replace;boundary=myboundary....--myboundary..Content-Type: image/jpeg..Content-Length: 30146......
I've double-checked with browser developer tools and I can confirm that sending the request from browser or from httpClient yield the same exact request. Furthermore right-clicking on the request url and issueing "open in new tab" opens a tab where I can see the camera live stream in both cases.
Could you please help me in this?

Close console app after calling webapi without waiting for result

I'm trying to call a webapi from a console application (which is triggered by windows task scheduler). I don't want my console app to wait for the result from api.I just want to call api and initiate it and exit the console application.
My console application code is
public static void InvokeSisService(string feature)
{
var serviceurl = ConfigurationManager.AppSettings["AppServiceURL"];
var controllerPath= ConfigurationManager.AppSettings["ControllerPath"];
var client = new HttpClient { BaseAddress = new Uri(serviceurl) };
controllerPath= controllerPath+ "?feature=" + feature;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
//client.PostAsync(smsservicepath, null);
// var temp=client.GetAsync(smsservicepath).Result;
var response = Task.Run(() => client.GetAsync(controllerPath)).Result;
}
My webapi is being called but it was waiting for the output.How do i exit console app after calling api.
Webapi code
[HttpGet]
[Route("ProcessService")]
public HttpResponseMessage ProcessService([FromUri] string feature)
{
}
I'm sure you want to make sure the response was received, so change
var response = Task.Run(() => client.GetAsync(controllerPath)).Result;
To:
using (var response = await client.GetAsync(controllerPath, HttpCompletionOption.ResponseHeadersRead))
This will drop after the response headers have been received. This does NOT include error handling - you should probably add error handling to the mix to make sure you are getting a proper response code before moving on - but that's up to you.
var response = Task.Run(() =>
client.GetAsync(controllerPath)).Result;
with the property "Result" you are waiting for the Response.

WP8 Fast App Resume with Asynchronous methods

In my windows phone 8 app i am using asynchronous methods to retrieve data from server.
After implementing Fast App Resume functionality another problem rose for me. The asynchronous method that retrieves data from server throws the exception of type System.Net.WebException when it resumes.
The steps to reproduce the problem is you just hit the start button when the app is loading data by asynchronous method.
For example i have a page that loads notification of user. I called the async void GetNotifications() method that further calls below method to retrieve response string.
public async Task<string> Get(string URL)
{
var request = WebRequest.Create(new Uri(URL)) as HttpWebRequest;
if (APIHelper.APIHandshake != null)
request.Headers["Cookie"] = "ii=" + APIHelper.APIHandshake.Sid + ";";
return await httpRequest(request);
}
the implementation of httprequest method is given below.
private async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory
.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
//cookieJar = request.CookieContainer;
//responseCookies = response.Cookies;
received = await sr.ReadToEndAsync();
}
}
}
return received.Replace("[{}]", "[]")
.Replace("[{},{}]", "[]")
.Replace("\"subcat_id\":\"\"", "\"subcat_id\":\"0\"");
}
The user just click the menu that opens the notification page and then press the start button of phone instantly to deactivate the app. When user will click on application tile from start menu the exception will be thrown.
Any solution? will deactivating idle mode detection work?
It would probably not be the best solution but It is possible to not cancel the async request by adding this line of code in the InitalizePhoneApplication() method on your app.xaml.cs page.
PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
Read more on this property here
Test it, it should fix the issue but I'm not pretending that's the best thing to do....

Get application to wait until Variables are updated

I am working with OAuth at the moment. The problem with the current code is it doesn't wait until the user allows the application on the site and gets the proper key and secret. I was using a threading type wait but, sometimes it not long enough...some users are slower then others. I have attached a snippet of my code. What I would like to know is where to insert a while statement, or should I even use that ?
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
var response = request.GetResponse();
var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
You should switch over to the newer System.Net.Http and System.Net.Http.WebRequest libraries that come with .NET now. These all use the new async programming stuff that is available with .NET 4.5.
You can call a request (returning you a task object that you can wait on) and automatically pause the thread for the response. The UI won't respond, as normal. That is probably the easiest thing to do if you don't understand how the new async and await keywords work. For more information on them, see http://msdn.microsoft.com/en-us/library/hh191443.aspx
Here is your code doing things with the new libraries:
using System.Net.Http;
public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
{
var uri = new Uri(baseUri, "oauth/request_token");
uri = SignRequest(uri, consumerKey, consumerSecret);
var message = new HttpRequestMessage(new HttpMethod("GET"), uri);
var handler = new WebRequestHandler();
var client = new HttpClient(handler);
// Use the http client to send the request to the server.
Task<HttpResponseMessage> responseTask = client.SendAsync(message);
// The responseTask object is like a wrapper for the other task thread.
// We can tell this task object that we want to pause our current thread
// and wait for the client.SendAsync call to finish.
responseTask.Wait();
// - Once that thread finishes, and the code continues on, we need to
// tell it to read out the response data from the backing objects.
// - The responseTask.Result property represents the object the async task
// was wrapping, we want to pull it out, then use it and get the content
// (body of the response) back.
// - Getting the response actually creates another async task (the
// .ReadAsStringAsync() call) but by accessing the .Result
// property, it is as if we called .ReadAsStringAsync().Wait(); Except that
// by using Result directly, we not only call Wait() but we get the resulting,
// wrapped object back. Hope that didn't confuse you much :)
var queryString = responseTask.Result.Content.ReadAsStringAsync().Result;
// And all your other normal code continues.
var parts = queryString.Split('&');
var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);
return new OAuthToken(token, secret);
}
Why Not use a modal pop up and then call the authentication class on the submit button

Categories

Resources