我将HttpListener类用于简单的多头HTTP服务器以进行长轮询操作。我使用AutoResetEvents和WaitHandle.WaitAny进行线程之间的信号消息传递。应用程序在.NET 4.5上运行良好。但是在Mono上移植应用程序后,我们遇到了一些多线程问题(版本3.2.8(Debian 3.2.8 + dfsg-4ubuntu1))。
我们预计当第一个HTTP请求的服务器处理接收到第二个HTTP请求时应该完成。等等。但是在Mono处理第一个请求只能通过超时完成。 我的申请的简化代码如下。
class Program
{
private static AutoResetEvent autoEvent = new AutoResetEvent(false);
private static AutoResetEvent autoEvent2 = new AutoResetEvent(false);
public static void Main()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:2999/");
listener.Start();
Console.WriteLine("Listening...");
BeginGetContext(listener);
Console.ReadLine();
}
public static void BeginGetContext(HttpListener listener)
{
Console.WriteLine("BeginGetContext...");
while (listener.IsListening)
{
var asyncResult = listener.BeginGetContext(ListenerCallback, listener);
asyncResult.AsyncWaitHandle.WaitOne();
}
}
public static void ListenerCallback(IAsyncResult result)
{
Console.WriteLine("ListenerCallback...");
autoEvent.Set();
autoEvent.Reset();
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
// some code
//...
int res = WaitHandleNext();
if (res == 0 || res == 1)
{
// Never get this line
Console.WriteLine("Done...");
}
else if (res == WaitHandle.WaitTimeout)
{
// Always here
Console.WriteLine("Done by timeout");
}
}
private static int WaitHandleNext()
{
Console.WriteLine("WaitHandleNext...");
int waitResult = WaitHandle.WaitAny(new[] { autoEvent, autoEvent2 }, TimeSpan.FromSeconds(30), false);
return waitResult;
}
}
如果我在autoEvent.Set和autoEvent.Reset之间放置Thread.Sleep(10),我会得到预期的行为,但并非总是如此。
autoEvent.Set();
Thread.Sleep(10);
autoEvent.Reset();
我不知道Mono的预期行为,Mono中的bug或我的应用程序错误。 如何才能在.Net上的Mono上实现我的应用程序的行为?任何变通办法或其他帮助都会很棒。