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を使用しています。