http请求入队列排队执行以及遇到的问题总结
队列以及加锁的注意事项,如下所示,记录之,线程的知识体系尚需完善。
public class HttpContext
{
public HttpListenerContext httpListenerContext { get; set; }
public Hashtable para { get; set; }
}
public partial class Form1 : Form
{
private HttpListener m_verifyhttplisten;
private object m_listenlocker = new object();
private ConcurrentQueue<HttpContext> m_httpconQueue = new ConcurrentQueue<HttpContext>();
HttpContext m_httpContext = new HttpContext();
HttpListenerContext httpListener;
object locker = new object();
static int num = 1;
public Form1()
{
InitializeComponent();
m_verifyhttplisten = new HttpListener();
m_verifyhttplisten.Prefixes.Add("http://192.168.1.199:50000/verify/");
m_verifyhttplisten.Start();
ThreadPool.QueueUserWorkItem(new WaitCallback(obj =>
{
httpRequestHandle2();
}));
Thread thread2 = new Thread(ceshi);
thread2.Start();
}
private void httpRequestHandle2()
{
while (true)
{
try
{
//等待请求连接,没有请求则GetContext处于阻塞状态
HttpListenerContext requestContext = m_verifyhttplisten.GetContext();
ThreadPool.QueueUserWorkItem(new WaitCallback(verifyhttplistern), requestContext);
}
catch (Exception ex)
{
//LogHelperBLL.CreateErrorLogTxt("httpRequestHandle2", ex.Source, ex.Message);
}
}
}
private void verifyhttplistern(object requestcontext)
{
try
{
lock (m_listenlocker)
{
//获取请求参数
Hashtable para = new Hashtable();
//返回值
Hashtable rtn = new Hashtable();
//客户端发送过来的信息
HttpListenerContext request = (HttpListenerContext)requestcontext;
//获取Post请求中的参数和值帮助类
HttpListenerHelper httppost = new HttpListenerHelper(request);
//获取Post过来的参数和数据
List<HttpListenerPostValue> lst = httppost.GetHttpListenerPostValue();
try
{
HttpContext httpContext = new HttpContext();
httpContext.httpListenerContext = request;
httpContext.para = para;
try
{
m_httpconQueue.Enqueue(httpContext);
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
}
}
private void ceshi()
{
while (true)
{
try
{
Hashtable para = new Hashtable();
Hashtable rtn = new Hashtable();
lock (locker)
{
HttpContext httpContext = new HttpContext();
if (m_httpconQueue.Count > 0)
{
m_httpconQueue.TryDequeue(out httpContext);
}
else if (m_httpconQueue.Count == 0)
{
continue;
}
HttpListenerContext request = httpContext.httpListenerContext;
para = httpContext.para;
try
{
rtn.Add("status", 200);
rtn.Add("code", 1);
rtn.Add("message", "ceshi");
//Response
request.Response.StatusCode = 200;
request.Response.Headers.Add("Access-Control-Allow-Origin", "*");
request.Response.ContentType = "application/json";
request.Response.ContentEncoding = Encoding.UTF8;
byte[] buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(rtn));
request.Response.ContentLength64 = buffer.Length;
var output = request.Response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
catch (System.Net.WebException ex)
{
Console.WriteLine(ex.Message);
}
}
Thread.Sleep(100);
}
catch (Exception ex)
{
}
}
}
}
上面的程序段时不时的会报“提交响应后无法执行此操作 ”这个错误。我就一直被这个错误困扰误导了,一直沿着这个方向找问题。后来发现我找问题的方向是不对的。而是应该是线程安全方面的问题。队列入队的对象加锁出现问题,导致出队列执行响应的时候报这个异常。即:入队的时候的这个对象应该是局部变量,加在锁内。
如上图所示:入队的这个对象是全局的对象,就会导致异常。