0

私は次の場所にある HttpListenter のものをいじっています:

http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx

標準のコンソール アプリでは問題なく動作しますが、Windows サービスとして動作させようとしています。アプリケーション ログは、サービスの起動時に HttpListener.Start() メソッドで失敗することを示しています。なぜこれが起こるのか、私はかなり困惑しています。

これがクラスです(概念の品質の証明はここにあります:)

public class Server
{
    public Server()
    {
        var thread = new Thread((Start));
        thread.Start();
    }

    public static void Start()
    {
        while(Listen())
        {
        }
    }

    private static bool Listen()
    {
        var prefixes = new[] {"http://192.168.0.7/"};

        if (!HttpListener.IsSupported)
        {
            Console.WriteLine ("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
            return false;
        }
        // URI prefixes are required, 
        // for example "http://contoso.com:8080/index/".
        if (prefixes == null || prefixes.Length == 0)
          throw new ArgumentException("prefixes");

        // Create a listener.
        HttpListener listener = new HttpListener();

        // Add the prefixes. 
        foreach (string s in prefixes)
        {
            listener.Prefixes.Add(s);
        }

        listener.Start();   //THIS FAILS IN WINDOWS SERVICE AS LOCAL SYSTEM

        //Console.WriteLine("Listening...");
        //// Note: The GetContext method blocks while waiting for a request. 
        //HttpListenerContext context = listener.GetContext();
        //HttpListenerRequest request = context.Request;
        //// Obtain a response object.
        //HttpListenerResponse response = context.Response;
        //// Construct a response. 
        //string responseString = "<HTML><BODY> " + DateTime.Now + "</BODY></HTML>";
        //byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        //// Get a response stream and write the response to it.
        //response.ContentLength64 = buffer.Length;
        //System.IO.Stream output = response.OutputStream;
        //output.Write(buffer,0,buffer.Length);
        //// You must close the output stream.
        //output.Close();
        //listener.Stop();

        return true;
    }

}

関連ログ: エラー:

Application: Stout.Workers.Service.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Net.HttpListenerException
Stack:
   at System.Net.HttpListener.Start()
   at Stout.Workers.Service.Server.Listen()
   at Stout.Workers.Service.Server.Start()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

エラー:

Faulting application name: Stout.Workers.Service.exe, version: 0.0.0.0, time stamp: 0x50d0cd99
Faulting module name: KERNELBASE.dll, version: 6.2.9200.16451, time stamp: 0x50988950
Exception code: 0xe0434352
Fault offset: 0x00014b32
Faulting process id: 0x1e70
Faulting application start time: 0x01cddd5bb3e8500b
Faulting application path:     C:\Users\Chad\Dropbox\Personal\Projects\Stout\Stout\Workers\Service\bin\Debug\Stout.Workers.Service.exe
Faulting module path: C:\Windows\SYSTEM32\KERNELBASE.dll
Report Id: f1aa9986-494e-11e2-be9b-685d43b0551c
Faulting package full name: 
Faulting package-relative application ID: 

情報:

Fault bucket , type 0
Event Name: CLR20r3
Response: Not available
Cab Id: 0

Problem signature:
P1: stout.workers.service.exe
P2: 0.0.0.0
P3: 50d0cd99
P4: System
P5: 4.0.30319.18016
P6: 505702c9
P7: 206c
P8: 5c
P9: System.Net.HttpListenerException
P10: 
4

1 に答える 1

1

リスナーで複数のリクエストを受け入れようとしていると思います。コードを注意深く読むと、複数の呼び出しを処理する単一のリスナーを作成するのではなく、無限の数のリスナーをインスタンス化していることがわかります。

実際に取得している例外は StackOverflowException (ブロックでキャッチできない唯一の例外try-catch) です。アプリケーションは何をしても壊れます。

ループを削除しwhile(Listen を 1 回呼び出すだけ)、Listen メソッドで次のアプローチを使用してみてください。

HttpListener listener = new HttpListener();
//add your prefixes here
listener.Start();
AsyncCallback processRequest = delegate(IAsyncResult result)
{
    //set the listener to listen for next request
    listener.BeginGetContext(processRequest, listener);
    HttpListenerContext context = listener.EndGetContext(result);
    //Your code to handle the request here
}

listener.BeginGetContext(processRequest, listener);

これにより、探しているループが単一で作成されますHttpListener

お役に立てれば

UPDATElistener.GetContext() : リクエスト処理コードのコメントを外すと、呼び出し時にスレッドをブロックし、リクエストを受信して​​ Listen メソッドが返らないまでリスナーがハングするため、例外が発生しないことに注意してください。which をすぐに呼び出しlistener.Start()てから true を返すだけで、非常に高速な速度でループし、多くのリスナーを作成します。

あなたのコードはこのように動作するかもしれませんが、リクエストごとにリスナーを作成する必要があるため、効率的ではありません。要求の 1 つが実行に 10 秒かかる場合、要求元のクライアントに応答するまでループは別のリスナーを作成しないため、単一のリスナーがすべての要求を非同期で処理できるようにすることをお勧めします。

于 2012-12-18T20:51:59.210 に答える