WCF关闭ServiceHost时等待操作完成

时间:2011-05-16 11:16:45

标签: c# .net wcf soap

我创建了一个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?也就是说,我想要禁用服务侦听器,还要等待所有当前连接的客户端完成(或指定最大超时)。

4 个答案:

答案 0 :(得分:4)

我很惊讶,呼叫ServiceHost.Close不让LongRunningOperation完成。

整个架构设置为允许时间优雅地关闭(例如,关闭和中止转换之间的差异)。根据MSDN文档:

  

这种方法导致了   CommunicationObject优雅地   从任何国家过渡,除了   关闭状态,进入关闭状态   州。 Close方法允许任何   未完成的工作要完成   返回。

此外,ServiceHost上还有一个CloseTimeout。您是否尝试将CloseTimeout设置为大于20秒? (根据Reflector,ServiceHost的默认CloseTimeout是10秒......)

答案 1 :(得分:2)

你在做什么似乎对我来说都是错的。 ServiceHost永远不应该突然关闭。这是一项服务,应该仍然可用。没有客户的参与,没有真正的方法可以优雅地关闭。当我优雅地说,从客户的角度来看,这也是主观的。

所以我认为我完全理解你的要求,但是一种方法是实现发布/订阅模式,当主机准备好关闭时,通知所有订阅者这个事件,以便每个连接可以关闭各自的客户。您可以在http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

了解更多相关信息

同样,这种托管服务的方法并不标准,这就是为什么你很难找到解决你这个特定问题的方法。如果您可以详细说明您的用例/使用场景,那么找到一个真正的解决方案可能会有所帮助。

答案 2 :(得分:2)

原则上,我认为以下内容应该是可行的,但我没有实现它以确认所有细节:

  • 实现自定义IOperationInvoker 包装Dispatcher的正常 OperationInvoker(在构建服务调度程序运行时时,您需要IServiceBehavior来安装包装的调用程序)
  • 自定义调用程序主要委托给真正的调用程序,但也会提供 转门的“守门人”功能 服务主机的新请求(例如引发某种异常) 要被关闭
  • 它还会跟踪操作调用 进度并在上次操作调用完成或超时时设置事件。
  • 主要托管线程将在调用serviceHost.Close()之前等待调用者的“全部完成”事件。

答案 3 :(得分:1)

您正在描述客户端功能。听起来你应该包装servicehost对象,然后让你的代理在“关闭”时拒绝新的请求。在所有呼叫都得到服务之前,您不会关闭真实的服务主机。

您还应该查看异步CTP。使用即将到来的TaskCompletionSource类,将这种逻辑放在消费者端“Task”对象会更容易。

从dnrtv中检查this video。这不是关于wcf,而是关于即将到来的异步语言和类支持。