I have a single thread process that has been running for a while. I need several users to have access to complete this process, and I choose the http protocol for call control.
Naturally, when one process is running, everyone else should wait until this happens. If a process is available, it runs. If not, then a BUSY response is sent.
Here is the implementation:
using System; using System.Net; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace simplehttp { class Program { private static System.AsyncCallback task; private static System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false);// Notifies one or more waiting threads that an event has occurred. private static HttpListenerContext workingContext = null; public static bool isBackgroundWorking() { return mre.WaitOne(0); } static void Main(string[] args) { new Thread(() => { Thread.CurrentThread.IsBackground = true; while (true) { Console.WriteLine(" waitOne " + isBackgroundWorking()); mre.WaitOne(); // Blocks the current thread until the current WaitHandle receives a signal. Console.WriteLine(" do job" + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId + " ]\n"); HttpListenerRequest request = workingContext.Request; HttpListenerResponse response = workingContext.Response; string responseString = "WORK " + DateTime.Now ; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; System.IO.Stream output = response.OutputStream; Thread.Sleep(10000); output.Write(buffer, 0, buffer.Length); output.Close(); Console.WriteLine(" " + responseString + "\t" + DateTime.Now); workingContext = null; mre.Reset(); // Sets the state of the event to nonsignaled, causing threads to block. } }).Start(); // Create a listener. HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://localhost:6789/index/"); listener.Start(); Console.WriteLine("Listening..." + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId + " ]\n"); task = new AsyncCallback(ListenerCallback); IAsyncResult resultM = listener.BeginGetContext(task,listener); Console.WriteLine("Waiting for request to be processed asyncronously."); Console.ReadKey(); Console.WriteLine("Request processed asyncronously."); listener.Close(); } private static void ListenerCallback(IAsyncResult result) { HttpListener listener = (HttpListener) result.AsyncState; //If not listening return immediately as this method is called one last time after Close() if (!listener.IsListening) return; HttpListenerContext context = listener.EndGetContext(result); listener.BeginGetContext(task, listener); if (workingContext == null && !isBackgroundWorking()) { // Background work workingContext = context; mre.Set(); //Sets the state of the event to signaled, allowing one or more waiting threads to proceed. } else { HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; string responseString = "BUSY "+ DateTime.Now + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; System.IO.Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); output.Close(); Console.WriteLine(responseString + "\t" + DateTime.Now); } } } }
To check that I am making 2 http calls. I expect that I have 2 different answers WORK and BUSY. However, I see that the second request waits before it finishes and then executes.
waitOne False Listening... [:10 ] Waiting for request to be processed asyncronously. do job [:11 ] WORK 1/24/2016 10:34:01 AM 1/24/2016 10:34:11 AM waitOne False do job [:11 ] WORK 1/24/2016 10:34:11 AM 1/24/2016 10:34:21 AM waitOne False
What is wrong in my understanding of how this should work?
Update (too many comments not encouraged by SO): My code looks awkward because it is a replication of the real process. In a βmyβ application, a workflow is the main process that has the βcivilityβ to run C # inline code at certain points. Thus, I cannot start a new task to process the request, and it should be asynchronous, since the workflow does its own work and only calls the subordinate part of the code to notify clients when data is available. This is asynchronous because the code is called and should end as soon as possible or it blocks the main application. I will try to add an additional thread with a synchronous call and see how it affects the situation.
The debugger is not used in this example so as not to interfere with the real-time technology and time stamps printed on the console. Debugging is great and necessary, but in this case I am trying to replace the output to avoid using an extra actor in a synchronization / wait script.
The application itself is not a heavy loaded conversation. 1-3 clients rarely request a basic application for a response. The http protocol is used for convenience not for heavy or frequent conversations. It seems that some browsers, such as IE, are working fine (Windows for Windows communication?), And some like Chrome (more system agnostics) replicate the behavior of my application. Look at the timestamps, Chrome, IE, IE, Chrome and the last Chrome still go to the WORK process. BTW, the code is changed for each sentence of the conversation, and now a new request is placed immediately after receiving the previous one.
HttpListenerContext context = listener.EndGetContext(result); listener.BeginGetContext(task, listener);

In addition to the following sentences, I changed the syncroniuos asynchronous call, and the result is still the same
private static void ListenerCallback(IAsyncResult result) { HttpListener listener = (HttpListener) result.AsyncState; //If not listening return immediately as this method is called one last time after Close() if (!listener.IsListening) return; HttpListenerContext context = listener.EndGetContext(result); while (true) { if (workingContext == null && !isBackgroundWorking()) { // Background work workingContext = context; mre.Set(); //Sets the state of the event to signaled, allowing one or more waiting threads to proceed. } else { HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; string responseString = "BUSY " + DateTime.Now + " [" + Thread.CurrentThread.Name + ":" + Thread.CurrentThread.ManagedThreadId; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString); response.ContentLength64 = buffer.Length; System.IO.Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); output.Close(); Console.WriteLine(responseString + "\t" + DateTime.Now); } context=listener.GetContext(); } }