|
George_George wrote: result = _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server) while at the same time, Stop is called. [Smile]
George - I was trying to solve the quoted issue. When I looked into your code carefully, I am confused. Your HTTPServer can connect only one client at a time ?
|
|
|
|
|
Thanks N a v a n e e t h,
1.
I have checked multiple clients can enter HandleRequest when we call EndGetContext. Please feel free to correct me if I am wrong.
2.
If you have any ideas to improve my code to handle clients' request more efficiently?
regards,
George
|
|
|
|
|
Ok- Take a look at your StartListen() method (unwanted lines trimmed).
public void StartListen()
{
IAsyncResult result;
_Server.Start();
while (true)
{
result = _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server);
result.AsyncWaitHandle.WaitOne();
}
}
Consider the following situation
1 - Loop starts for the first time, value of result will be NULL initially.
2 - It calls _Server.BeginGetContext , asynchronous method call starts and return immediatly.
3 - You call WaitOne() which blocks the loop, so it will wait until the processing finishes.
4 - When processing finishes it waits for next one.
So what will happen if another request comes during the execution of previous one ? It will be blocked in this case. Correct ?
|
|
|
|
|
Thanks N a v a n e e t h,
When I call EndGetContext, the server is able to process another request, while at the same time, in method HandleRequest, we can retrive input stream and output stream of Http Request from parameter HttpListenerContext context, so that at the same time of waiting for another incoming request, we can read content of request from input stream and processing, then write output to the output stream.
Please feel free to correct me if I am wrong. Also, if you have any ideas to improve, I am happy to learn from you.
regards,
George
|
|
|
|
|
George_George wrote: When I call EndGetContext, the server is able to process another request
yes, it will be able to process other request only at that time. So all the requests came when it executes, has to wait. Other problem I find here is, the IAsyncResult instance is shared, I mean it will be overwritten each time a request occurs. This is not a good idea. One IAsyncResult instance should represent one request, Right ?
Looks like you need to refactor this. Consider a design where each request will have it's own IAsyncResult instance. I guess that should solve the problem
|
|
|
|
|
Thanks N a v a n e e t h,
1.
Do you mean the pattern in my code is not truly handles incoming requests at the same time? I do not agee, since I have debugged that, when we call EndGetContext,
- then result.AsyncWaitHandle.WaitOne() will return and BeginGetContext is able to run and let next request come in;
- at the same time, we can execute HandleRequest for the last request.
Why do you think it is not truly handling client requests simultaneously? Could you show me your improvement please?
2.
N a v a n e e t h wrote: Looks like you need to refactor this. Consider a design where each request will have it's own IAsyncResult instance. I guess that should solve the problem
Are there any benefits doing this? Could you show me a couple of lines of pseudo code please?
regards,
George
|
|
|
|
|
George_George wrote: Do you mean the pattern in my code is not truly handles incoming requests at the same time?
I felt so. Your code won't handle as you are calling WaitOne which will block it. Also the IAsyncResult instance will be overwritten each time. I am not telling that your code can't handle two requests, I am telling it can't handle simultaneous requests because of that blocking.
George_George wrote: Are there any benefits doing this? Could you show me a couple of lines of pseudo code please?
There are many. You can execute many requests simultaneously. Consider the following pseudo code
1 - Inside the StartListen method, remove call to WaitOne.
2 - Put IAsyncResult inside that loop. Which means IAsyncResult will be created for each request.
3 - Create another class for doing request handling, where you pass this IAsyncresult instance. So ultimately you will have each IAsyncResult instance for each request.
I am not sure about I am correct. But have a try and modify it according to your need.
|
|
|
|
|
Thanks N a v a n e e t h,
Really great answer! I further question before I am able to write code to re-construct. When will the event which WaitOne is wait on be signalled? When we call EndGetContext or when there is a ready asynchronous I/O client Http request ready -- at the time when the callback (as the first parameter to BeginGetContext) is called? Or something else?
regards,
George
|
|
|
|
|
George_George wrote: When will the event which WaitOne is wait on be signalled?
You don't need to call WaitOne. When the asynchronous method process, it will call back, there you can do EndGetContext to get the result.
|
|
|
|
|
Thanks N a v a n e e t h!
Is this your suggested solution?
Code change,
- removed IAsyncResult result;
- removed result.AsyncWaitHandle.WaitOne();
- change from result = _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server) to _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server);
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Net;
using System.Threading;
namespace TestServiceStop1
{
public partial class Service1 : ServiceBase
{
private Thread _tHttpThread;
private TestHttpServer _server;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_server = new TestHttpServer(this);
_tHttpThread = new Thread(_server.StartListen);
_tHttpThread.Start();
}
protected override void OnStop()
{
_server.Stop(false);
}
}
public class TestHttpServer
{
private int _Port = 0;
private HttpListener _Server = new HttpListener();
private Service1 _manager;
public TestHttpServer (Service1 manager)
{
_manager = manager;
}
public int ListenPort
{
get
{
return _Port;
}
set
{
_Port = value;
}
}
public void StartListen()
{
try
{
_Server.Prefixes.Add(String.Format("http://+:{0}/", 9099));
_Server.Start();
while (true)
{
_Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server);
}
}
catch (Exception ex)
{
throw ex;
}
}
public void Stop(bool isTerminate)
{
_Server.Stop();
}
private void HttpCallback(IAsyncResult result)
{
HttpListenerContext context = _Server.EndGetContext(result);
HandleRequest(context);
}
private void HandleRequest(HttpListenerContext context)
{
string matchUrl = context.Request.Url.AbsolutePath.Trim().ToLower();
context.Response.StatusCode = 200;
context.Response.StatusDescription = "OK";
context.Response.Close();
}
}
}
regards,
George
|
|
|
|
|
George_George wrote: while (true)
{
result = _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server);
result.AsyncWaitHandle.WaitOne();
}
In your StartListen you get in this endless loop. So after stopping the server the call to
_Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server); most likely throws this exception.
You will need to check if the _Server object is still active before calling the BeginGetContext I guess...
|
|
|
|
|
Thanks GDavy,
How do check whether _Server is still active? Any suggestions?
regards,
George
|
|
|
|
|
from MSDN on the BeginGetContext call[^]
The InvalidOperationException is thrown when the server is stopped. So there you go it is normal behaviour. You can check the IsListening Property to see if the _Server is started or not.
|
|
|
|
|
Thanks GDavy,
Your solution works. Cool!
regards,
George
|
|
|
|
|
you should put break for while loop...
while (true)
{
try
{
result = _Server.BeginGetContext(new AsyncCallback(this.HttpCallback), _Server);
result.AsyncWaitHandle.WaitOne();
}catch (HttpListenerException) { break; }
catch (InvalidOperationException) { break; }
}
|
|
|
|
|
George_George wrote: catch (Exception ex)
{
throw ex;
}
You're not doing anything with the exception and then you throw a modified exception (without the original stack trace).
If you want to re-throw the original exception use
throw; Simple.
|
|
|
|
|
|
hi i want an application that is used to create an auto updater
like anitvirus updater or windows updater.
what will i need to do please guide me
wasim khan
|
|
|
|
|
|
Hello all Technologist
Can some one help me distinguish between a DRM protected Audio/Video files on windows platform ? I don't wanna use Itune's SDK or WMF -SDK for the same . here i am looking seem general properties of Protected files which will just let me know .....if file is DRM protected or not .
Thanking you in anticipation.
Regards
Ritesh
aa
|
|
|
|
|
have you ever found an answer for this?
(2B)||(!2B)
|
|
|
|
|
We declare an array as
int arr[] = new int[5]; // <---a
now can we also declare the same array as
int[] arr = new int[5]; // <---b
Are both declaring the same array, or is there a diffrence in them?
|
|
|
|
|
humdumof wrote: We declare an array as
int arr[] = new int[5]; // <---a
Its incorrect syntax. How can you declare array like this?
|
|
|
|
|
well i think i got a little confused,
that i had read in a code written in java, & hadn't check with
c#. So, thats y i ask the question.
int[] arr = new int[5]; // is the correct way.
thanks for ur reply.
|
|
|
|
|
Creating arrays in C# has different syntax than other languages.
In C# it's like this:
int[] array = new int[5];
In other languages, like C, it's like this:
int array[5];
|
|
|
|