c# – 针对HttpListener的多线程应答
我有单线程进程,执行了很长时间.我需要几个用户才能访问执行此过程,我选择http协议来管理调用.
当然,当一个过程正在运行时,其他人应该等到它完成.如果进程可用,则执行.如果没有,则发送BUSY应答. 这是实施: 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,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,buffer.Length); output.Close(); Console.WriteLine(responseString + "t" + DateTime.Now); } } } } 为了测试我做2个http调用.我希望有2个不同的答案WORK和BUSY. 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 我理解它应该如何运作有什么问题? 更新(太多评论没有被SO鼓励): 此示例中未使用调试器来干扰打印到控制台的实时进程和时间戳.调试很棒且必要但在这种情况下我尝试用输出替换以避免同步/等待场景中的额外actor. 应用程序本身并不是繁重的对话. 1-3个客户很少向主要申请人询问答案. http协议用于方便而不是繁重或经常对话.看起来像IE这样的浏览器工作正常(Windows到Windows会话?),有些像Chrome(更多系统不可知)复制我的应用程序行为.看看时间戳,Chrome,IE,Chrome和最后一个Chrome仍然进入了WORK流程.顺便说一句,每个会话建议更改代码,现在在检索前一个请求后立即发出新请求. HttpListenerContext context = listener.EndGetContext(result); listener.BeginGetContext(task,listener); 另外,根据建议,我改变了对syncroniuos的异步调用,结果仍然相同 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,buffer.Length); output.Close(); Console.WriteLine(responseString + "t" + DateTime.Now); } context=listener.GetContext(); } } 解决方法
发布的代码与它应该完全一样:
无法重现.我想这回答了这个问题,因为显然你错误地推动了测试工作量.我通过反复点击Fiddler composer发送按钮开车. 谢谢你发布可执行代码.我应该早点尝试过! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |