解释为什么 "using" 不能在服务中工作?
Explain why "using" won't work in service?
所以我在这个问题上被困了大约一个星期。我正在尝试 运行 一个项目来接收 TCP 连接并启动 SignalR Hub 作为服务。两者都完美地 运行 将项目作为 .exe 文件。 TCP 部分可以完美运行,但是我在 SignalR 端遇到了问题。
最终原因是 using 语句。
之前
using (WebApp.Start<SignalrStartup>(url))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Server running on {0}", url); // was url
Console.WriteLine("ID\tMessage");
Console.ReadLine();
}
之后
WebApp.Start<SignalrStartup>(url);
我试过 运行 注释掉 Console.WriteLine()
的代码,因为我认为它可能会抛出异常,因为没有控制台可以输出一次 运行作为一项服务。这也没有用,但也不能作为 .exe 文件工作,因为它需要 Console.ReadLine()
来保持控制台打开,这就是你需要它的方式保持 HelloWorld.cs 打开。一旦 using 包装器与 console 一起被删除,它将在 .exe 中工作和服务。
我读到 using 语句会在您离开包装器后杀死其中的对象。但我不明白 After 代码如何使 .exe 代码在 运行ning 后打开。使用 using 有什么意义还是我用错了?
编辑
protected override void OnStart(string[] args)
{
Task.Factory
.StartNew(() => StartTCP())
.ContinueWith(t => StartSignalR());
}
正在从 StartSignalR()
方法进行调用。
你们的服务出了什么问题?
您遇到的问题是您的 Console.ReadLine
阻塞等待标准输入。这将永远阻塞 windows 服务,并导致服务控制管理器在 30 秒后超时启动服务。 This question 有更多关于正在发生的事情的信息。
如果您删除 using 语句的全部内容,并且语句本身就像您所做的一样,由 WebApp.Start
启动的服务器将在您的服务 Start
方法之后在后台继续运行完成。这是服务的正确行为。
你在这里有效地做的是泄漏 WebApp.Start
创建的异步工作者。这意味着它们在服务启动完成后仍然 运行 以侦听请求。
您可能应该跟踪 WebApp.Start
return 的 IDisposable
,并在 Stop
方法中处理它。
using
呢?
A using
statement 确保在控制离开 using
语句块时始终释放资源。这可能是由于抛出异常或因为块成功完成并且控制移至程序的下一部分。
using
当您知道块完成后没有人想要访问资源时使用语句。当您处理对您来说 return 和 IDisposable
的方法时,通常就是这种情况。但是,在您的情况下,您不想调用 dispose,因为您希望 WebApp.Start
创建的线程在服务启动后继续。
Webapp.Start<> 启动工作线程。即使在 HelloWorld.cs 中的代码执行完毕后,这些线程仍会保留您的 exe 运行。在所有工作线程停止之前,您的 exe 不会关闭。
当您添加 "using" 语句时,框架将在您的 SignalR 应用程序上调用 Dispose。此调用将停止所有工作线程,并且您的 exe 将终止。
Readline() 语句阻止应用程序到达 using 语句的末尾。这意味着在您按下 enter 之前不会调用 dispose 方法。
因此,对于 exe,您通常希望按照您的方式使用 ReadLine。
对于您想要存储对 IDisposable 的引用的服务,并在 Stop() 方法中对其调用处置。
所以我在这个问题上被困了大约一个星期。我正在尝试 运行 一个项目来接收 TCP 连接并启动 SignalR Hub 作为服务。两者都完美地 运行 将项目作为 .exe 文件。 TCP 部分可以完美运行,但是我在 SignalR 端遇到了问题。
最终原因是 using 语句。
之前
using (WebApp.Start<SignalrStartup>(url))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Server running on {0}", url); // was url
Console.WriteLine("ID\tMessage");
Console.ReadLine();
}
之后
WebApp.Start<SignalrStartup>(url);
我试过 运行 注释掉 Console.WriteLine()
的代码,因为我认为它可能会抛出异常,因为没有控制台可以输出一次 运行作为一项服务。这也没有用,但也不能作为 .exe 文件工作,因为它需要 Console.ReadLine()
来保持控制台打开,这就是你需要它的方式保持 HelloWorld.cs 打开。一旦 using 包装器与 console 一起被删除,它将在 .exe 中工作和服务。
我读到 using 语句会在您离开包装器后杀死其中的对象。但我不明白 After 代码如何使 .exe 代码在 运行ning 后打开。使用 using 有什么意义还是我用错了?
编辑
protected override void OnStart(string[] args)
{
Task.Factory
.StartNew(() => StartTCP())
.ContinueWith(t => StartSignalR());
}
正在从 StartSignalR()
方法进行调用。
你们的服务出了什么问题?
您遇到的问题是您的 Console.ReadLine
阻塞等待标准输入。这将永远阻塞 windows 服务,并导致服务控制管理器在 30 秒后超时启动服务。 This question 有更多关于正在发生的事情的信息。
如果您删除 using 语句的全部内容,并且语句本身就像您所做的一样,由 WebApp.Start
启动的服务器将在您的服务 Start
方法之后在后台继续运行完成。这是服务的正确行为。
你在这里有效地做的是泄漏 WebApp.Start
创建的异步工作者。这意味着它们在服务启动完成后仍然 运行 以侦听请求。
您可能应该跟踪 WebApp.Start
return 的 IDisposable
,并在 Stop
方法中处理它。
using
呢?
A using
statement 确保在控制离开 using
语句块时始终释放资源。这可能是由于抛出异常或因为块成功完成并且控制移至程序的下一部分。
using
当您知道块完成后没有人想要访问资源时使用语句。当您处理对您来说 return 和 IDisposable
的方法时,通常就是这种情况。但是,在您的情况下,您不想调用 dispose,因为您希望 WebApp.Start
创建的线程在服务启动后继续。
Webapp.Start<> 启动工作线程。即使在 HelloWorld.cs 中的代码执行完毕后,这些线程仍会保留您的 exe 运行。在所有工作线程停止之前,您的 exe 不会关闭。
当您添加 "using" 语句时,框架将在您的 SignalR 应用程序上调用 Dispose。此调用将停止所有工作线程,并且您的 exe 将终止。
Readline() 语句阻止应用程序到达 using 语句的末尾。这意味着在您按下 enter 之前不会调用 dispose 方法。
因此,对于 exe,您通常希望按照您的方式使用 ReadLine。 对于您想要存储对 IDisposable 的引用的服务,并在 Stop() 方法中对其调用处置。