等待一个长期存在的任务以知道它在没有阻塞的情况下开始
Await a long-lived Task to know it started without blocking
我很好奇社区对 运行 长期后台任务(在我的例子中是 HTTP 服务器)的最佳实践的感觉(知道)是什么。理想情况下,我希望能够等待 Start
方法,但不希望它阻止进一步执行。
看来我有两个选择:1) await(在该语句执行后什么也不做),或 2) 将 Task 分配给消费代码中的变量。
- 等待(即“等待连接”从不显示)
class Program
{
static HttpListener _Listener = null;
static string _ListenerPrefix = "http://localhost:8888/";
static Task _AcceptConnectionsTask = null;
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
await Start();
Console.WriteLine("Waiting for connections");
}
static Task Start()
{
_Listener.Start();
_AcceptConnectionsTask = Task.Run(() => AcceptConnections());
return _AcceptConnectionsTask;
}
static async Task AcceptConnections()
{
while (true)
{
HttpListenerContext ctx = await _Listener.GetContextAsync()
.ConfigureAwait(false);
await Task.Run(() => HandleConnection(ctx));
}
}
static async void HandleConnection(HttpListenerContext ctx)
{
string ip = ctx.Request.RemoteEndPoint.Address.ToString();
int port = ctx.Request.RemoteEndPoint.Port;
Console.WriteLine("Request received from " + ip + ":" + port + " "
+ ctx.Request.HttpMethod + " " + ctx.Request.Url);
// do stuff and respond...
}
}
- 分配给任务变量(显示“等待连接”)
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
// await Start();
Task t = Start();
Console.WriteLine("Waiting for connections");
Console.ReadLine();
}
我的问题是,有没有一种方法可以等待,以便我知道任务已启动而不排除紧随其后的语句的执行?
问题是 await Start()
不会阻塞。它异步等待任务完成而不阻塞。
“等待连接”消息应该在长 运行 任务完成之前打印到控制台,例如在您调用 GetContextAsync()
异步等待请求之前。
此外,您应该删除对 Task.Run
的调用,让程序“一直异步”而不涉及任何后台线程。像这样:
class Program
{
static HttpListener _Listener = null;
static string _ListenerPrefix = "http://localhost:8888/";
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
await Start();
}
static async Task Start()
{
_Listener.Start();
await AcceptConnections().ConfigureAwait(false);
}
static async Task AcceptConnections()
{
Console.WriteLine("Waiting for connections");
while (true)
{
HttpListenerContext ctx = await _Listener.GetContextAsync().ConfigureAwait(false);
HandleConnection(ctx);
}
}
static void HandleConnection(HttpListenerContext ctx)
{
string ip = ctx.Request.RemoteEndPoint.Address.ToString();
int port = ctx.Request.RemoteEndPoint.Port;
Console.WriteLine("Request received from " + ip + ":" + port + " " + ctx.Request.HttpMethod + " " + ctx.Request.Url);
// do stuff and respond...
}
}
您可能想要做的是将任务的创建与等待分开:
static async Task Main(string[] args)
{
//...
Console.WriteLine("Starting server on " + _ListenerPrefix);
Task t = Start();
Console.WriteLine("Waiting for connections (the task has been started)");
await t;
Console.WriteLine("The task has been completed");
}
我很好奇社区对 运行 长期后台任务(在我的例子中是 HTTP 服务器)的最佳实践的感觉(知道)是什么。理想情况下,我希望能够等待 Start
方法,但不希望它阻止进一步执行。
看来我有两个选择:1) await(在该语句执行后什么也不做),或 2) 将 Task 分配给消费代码中的变量。
- 等待(即“等待连接”从不显示)
class Program
{
static HttpListener _Listener = null;
static string _ListenerPrefix = "http://localhost:8888/";
static Task _AcceptConnectionsTask = null;
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
await Start();
Console.WriteLine("Waiting for connections");
}
static Task Start()
{
_Listener.Start();
_AcceptConnectionsTask = Task.Run(() => AcceptConnections());
return _AcceptConnectionsTask;
}
static async Task AcceptConnections()
{
while (true)
{
HttpListenerContext ctx = await _Listener.GetContextAsync()
.ConfigureAwait(false);
await Task.Run(() => HandleConnection(ctx));
}
}
static async void HandleConnection(HttpListenerContext ctx)
{
string ip = ctx.Request.RemoteEndPoint.Address.ToString();
int port = ctx.Request.RemoteEndPoint.Port;
Console.WriteLine("Request received from " + ip + ":" + port + " "
+ ctx.Request.HttpMethod + " " + ctx.Request.Url);
// do stuff and respond...
}
}
- 分配给任务变量(显示“等待连接”)
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
// await Start();
Task t = Start();
Console.WriteLine("Waiting for connections");
Console.ReadLine();
}
我的问题是,有没有一种方法可以等待,以便我知道任务已启动而不排除紧随其后的语句的执行?
问题是 await Start()
不会阻塞。它异步等待任务完成而不阻塞。
“等待连接”消息应该在长 运行 任务完成之前打印到控制台,例如在您调用 GetContextAsync()
异步等待请求之前。
此外,您应该删除对 Task.Run
的调用,让程序“一直异步”而不涉及任何后台线程。像这样:
class Program
{
static HttpListener _Listener = null;
static string _ListenerPrefix = "http://localhost:8888/";
static async Task Main(string[] args)
{
_Listener = new HttpListener();
_Listener.Prefixes.Add(_ListenerPrefix);
Console.WriteLine("Starting server on " + _ListenerPrefix);
await Start();
}
static async Task Start()
{
_Listener.Start();
await AcceptConnections().ConfigureAwait(false);
}
static async Task AcceptConnections()
{
Console.WriteLine("Waiting for connections");
while (true)
{
HttpListenerContext ctx = await _Listener.GetContextAsync().ConfigureAwait(false);
HandleConnection(ctx);
}
}
static void HandleConnection(HttpListenerContext ctx)
{
string ip = ctx.Request.RemoteEndPoint.Address.ToString();
int port = ctx.Request.RemoteEndPoint.Port;
Console.WriteLine("Request received from " + ip + ":" + port + " " + ctx.Request.HttpMethod + " " + ctx.Request.Url);
// do stuff and respond...
}
}
您可能想要做的是将任务的创建与等待分开:
static async Task Main(string[] args)
{
//...
Console.WriteLine("Starting server on " + _ListenerPrefix);
Task t = Start();
Console.WriteLine("Waiting for connections (the task has been started)");
await t;
Console.WriteLine("The task has been completed");
}