2

CancellationTokenSource.Token を使用したキャンセルをサポートする HttpListener.Listen() を使用してリクエストをリッスンするサーバーがあります。これはc# 4.0です。呼び出しコード:

Task.Factory.StartNew(() => 
{
    myServer = new MyServer();
    myServer.Listen(new[] { "http://*:8085/" }, cancel.Token);
});

マイサーバー:

public void Listen(IEnumerable<string> prefixes, CancellationToken cancel)
{
  httpListener = new HttpListener();
  foreach(var p in prefixes) httpListener.Prefixes.Add(p);

  httpListener.Start();

  // watch for cancellation
  while(!cancel.IsCancellationRequested)
  {
    var result = httpListener.BeginGetContext(callback =>
      {
        var listener = (HttpListener)callback.AsyncState;
        if(!listener.IsListening) return;

        var httpContext = listener.EndGetContext(callback);
        // handle the request in httpContext, some requests can take some time to complete
      }, httpListener);

    while(result.IsCompleted == false)
    {
      if(cancel.IsCancellationRequested) break;
      Thread.Sleep(100); // sleep and recheck
    }
  }
  httpListener.Stop();
}

これまでのところ問題なく動作しているように見えますが、コードが長すぎるようです。私はそのように FromAsync() を使用しようとしました:

public void Listen(IEnumerable<string> prefixes, CancellationToken cancel)
{
  httpListener = new HttpListener();
  foreach(var p in prefixes) httpListener.Prefixes.Add(p);

  httpListener.Start();

  while(!cancel.IsCancellationRequested)
  {
    Task.Factory.FromAsync<HttpListenerContext>(httpListener.BeginGetContext, httpListener.EndGetContext, null).ContinueWith(t =>
    {
      var httpContext = t.Result;
      // do stuff
    }, cancel);
  }
  httpListener.Stop();
}

しかし、whileループ内で多くのタスクが作成されるため、すぐにメモリ不足になります。この問題を解決する方法について何か提案はありますか? または私の最初の試みを片付ける方法は?他のいくつかのスレッドでいくつかの回答を見ましたが、プロジェクトが.net 4.0上にある間、それらは.net 5.0を使用しています。

4

0 に答える 0