Mono:AutoResetEvent无法预料的行为

时间:2014-07-29 14:32:31

标签: c# multithreading mono

我将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上实现我的应用程序的行为?任何变通办法或其他帮助都会很棒。

0 个答案:

没有答案