C#,在Windows服务的OnStart方法中调用异步方法

3

我正在开发一个能够接收套接字连接的 Windows 服务,因此在 OnStart 方法中:

protected override void OnStart(string[] args)
{
    start();
}

“start”函数长这个样子:start
public async void Start()
{
      //initialization things
      ...
      ...
      TcpListener listener = new TcpListener(IPAddress.Any, port);
      listener.Start();
      while(true)
      {
          TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
          ...
      }
      ...    
}

问题在于没有连接被接受,而同样的代码在标准命令行项目中运行得很好。我怀疑我的设计有问题,哪个线程运行了OnStart方法?当控制流程在await等待接受过程后返回OnStart时,异步方法是否被忽略了,因为它是Windows服务中的特殊情况?欢迎任何建议。

很可能是因为未捕获的异常导致了您的服务失败,因为任何异常都不会被捕获。请查看 Taskscheduler.UnobservedTaskException,检查您的事件日志并刷新您的服务屏幕。https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception?view=netframework-4.7.2 - Jesse de Wit
检查事件日志后,没有未观察到的异常 :( - ammcom
将该方法的签名更改为 async Task,然后再试一次。 - Jesse de Wit
哦,还有,请阅读此链接:https://dev59.com/TGw05IYBdhLWcg3w3ViX - Jesse de Wit
A) 不要使用异步 void B) 记录任何未观察到的异常 C) 在提交到服务之前尝试在控制台应用程序中运行,这样更容易调试 - TheGeneral
2个回答

7
当调用start()方法时,代码会立即继续执行并完成OnStart。现在你自己的代码中没有任何部分能够捕获任何异常。异常必须被TaskScheduler捕获。但是只有当Task被awaited或垃圾回收时才会发生这种情况。
因此,基本上,你的代码可能已经抛出了一个未被观察到的异常,直到Task被垃圾回收。为了更早地捕获和记录异常,请确保在任何地方都不要await方法内的异常:
protected override void OnStart(string[] args)
{
    Start();

    // This method finishes immediately (or at least after your first 
    // 'await' in the Start() method. That does not mean Start() runs 
    // on another thread however.
}

private async Task Start()
{
    try
    {
        //initialization things
        ...
        ...
        TcpListener listener = new TcpListener(IPAddress.Any, port);
        listener.Start();
        while(true)
        {
            TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
            ...
        }
        ...   
    }
    catch (Exception ex)
    {
        // TODO: LOG! And probably stop the service too.
    } 
}

尽管这不是我的问题,但这个答案帮助我改进了代码,谢谢。 - ammcom
仍然没有记录异常吗? - Jesse de Wit

0

看起来是Windows防火墙的问题,当我将代码作为控制台应用程序测试时,Windows防火墙会弹出确认消息询问是否允许打开端口,但是当我将其作为服务测试时,防火墙会默默地阻止传入连接而没有任何通知。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接