WCF 关闭 ServiceHost 时等待操作完成
我创建了一个 WCF SOAP 服务器,其操作需要一些时间才能执行:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string LongRunningOperation();
}
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false,
InstanceContextMode = InstanceContextMode.Single)]
class MyService : IMyService
{
public string LongRunningOperation()
{
Thread.Sleep(20000);
return "Hey!";
}
}
class Program
{
static void Main(string[] args)
{
MyService instance = new MyService();
ServiceHost serviceHost = new ServiceHost(instance);
BasicHttpBinding binding = new BasicHttpBinding();
serviceHost.AddServiceEndpoint(typeof(IMyService), binding, "http://localhost:9080/MyService");
serviceHost.Open();
Console.WriteLine("Service running");
Thread.Sleep(10000);
serviceHost.Close();
Console.WriteLine("Service closed");
Thread.Sleep(30000);
Console.WriteLine("Exiting");
}
}
ServiceHost 打开,10 秒后将其关闭。
当调用 serviceHost.Close() 时,当前连接的所有等待 LongRunningOperation 完成的客户端都会立即断开连接。
是否需要等待以更干净的方式关闭 ServiceHost?也就是说,我想禁用服务侦听器,但还要等待所有当前连接的客户端完成(或指定最大超时)。
I create a WCF SOAP server with an operation that takes some time to perform:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string LongRunningOperation();
}
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false,
InstanceContextMode = InstanceContextMode.Single)]
class MyService : IMyService
{
public string LongRunningOperation()
{
Thread.Sleep(20000);
return "Hey!";
}
}
class Program
{
static void Main(string[] args)
{
MyService instance = new MyService();
ServiceHost serviceHost = new ServiceHost(instance);
BasicHttpBinding binding = new BasicHttpBinding();
serviceHost.AddServiceEndpoint(typeof(IMyService), binding, "http://localhost:9080/MyService");
serviceHost.Open();
Console.WriteLine("Service running");
Thread.Sleep(10000);
serviceHost.Close();
Console.WriteLine("Service closed");
Thread.Sleep(30000);
Console.WriteLine("Exiting");
}
}
The ServiceHost is opened, and after 10 seconds I close it.
When calling serviceHost.Close(), all clients currently connected, waiting for LongRunningOperation to finish, are inmediately disconnected.
Is there a wait of closing the ServiceHost in a cleaner way? That is, I want to disable the service listeners, but also wait for all currently connected clients to finish (or specify a maximum timeout).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我很惊讶调用 ServiceHost.Close 并没有让 LongRunningOperation 完成。
整个架构的设置是为了让事情有时间正常关闭(例如关闭和中止转换之间的差异)。根据 MSDN 文档:
ServiceHost 上还有一个 CloseTimeout 正是用于此目的。您是否尝试过将 CloseTimeout 设置为大于 20 秒? (根据 Reflector,ServiceHost 的默认 CloseTimeout 为 10 秒...)
Im surprised calling ServiceHost.Close is not letting LongRunningOperation complete.
The whole architecture is setup to allow things time to gracefully shut down (e.g. the difference between Close and Abort transitions.). According to MSDN docs:
Also there is a CloseTimeout on the ServiceHost for precisely this. Have you tried setting the CloseTimeout to be greater than 20 seconds? (According to Reflector the default CloseTimeout for ServiceHost is 10 seconds...)
原则上,我认为类似以下的事情应该是可能的,尽管我还没有实现它来确认所有细节:
包装调度程序的正常
OperationInvoker(在构建服务调度程序运行时时,您需要一个 IServiceBehavior 来安装包装的调用程序)
“看门人”功能拒绝
当服务主机即将到来时新请求(例如引发某种异常)
被关闭。
进度并在最后一次操作调用完成或超时时设置事件。
serviceHost.Close()
之前等待调用者的“全部完成”事件。In principle, I think something like the following should be possible, though I haven't implemented it to confirm all the details:
wrapping the Dispatcher's normal
OperationInvoker (you'll want an
IServiceBehavior
to install the wrapped invoker when the service dispatcher runtime is built)"gate-keeper" functionality to turn away
new requests (e.g. raise a some kind of exception) when the service host is about
to be shut down.
progress and set an event when the last operation invocation finishes or times out.
serviceHost.Close()
.你所做的事在我看来都是错误的。 ServiceHost 永远不应该突然关闭。它是一项服务,应该保持可用。如果没有客户的参与,就没有真正的方法可以优雅地结束。当我说“优雅地关闭”时,从客户的角度来看,这也是主观的。
所以我认为我根本不理解您的要求,但是一种方法是实现发布/订阅模式,当主机准备关闭时,通知所有订阅者此事件,以便每个客户端都可以关闭所有连接。您可以在此处阅读有关此内容的更多信息 http://msdn.microsoft.com/en- us/magazine/cc163537.aspx
同样,这种托管服务的方法不是标准的,这就是为什么您发现很难找到针对您的这个特定问题的解决方案。如果您可以详细说明您的用例/使用场景,可能会有助于找到真正的解决方案。
What you are doing seems all wrong to me. The ServiceHost should never close abruptly. It is a service and should remain available. There is no real way to close gracefully without some participation from the client. When I say close gracefully, this also subjective from a clients perspective.
So I dont think I understand your requirements at all, however one way would be to implement a publish/subscribe pattern and when the host is ready to close, notify all subscribers of this event so that all connections could be closed by each respective client. You can read more about this here http://msdn.microsoft.com/en-us/magazine/cc163537.aspx
Again, this approach to hosting a service is not standard and thats why you are finding it hard to find a solution to this particular problem of yours. If you could elaborate on your use case/usage scenario, it would probably help to find a real solution.
您正在描述客户端功能。听起来您应该包装 servicehost 对象,然后让您的代理在“关闭”时拒绝新请求。在所有调用都得到服务之前,您不会关闭真正的服务主机。
您还应该看看异步 CTP。使用即将推出的 TaskCompletionSource 类,将这种逻辑放入消费者端“Task”对象中将会容易得多。
从 dnrtv 中查看此视频。这与 wcf 无关,而是与即将推出的异步语言和类支持有关。
You are describing client side functionality. Sounds like you should wrap the servicehost object and then have your proxy rejecting new requests when it "is closing". You don't close the real servicehost until all calls have been serviced.
You should also take a look at the asynch CTP. To put this kind of logic inside a consumer side "Task" object will be much easier with the upcoming TaskCompletionSource class.
Check this video from dnrtv out. It's not about wcf, but rather about the upcoming language and class support for asynchrony.