WCF 关闭服务主机时等待操作完成

本文关键字:等待 操作 主机 服务 WCF | 更新日期: 2023-09-27 17:56:38

我创建了一个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");
    }
}

服务主机被打开,10 秒后我关闭它。

调用 serviceHost.Close() 时,当前连接的所有客户端(等待 LongRunningOperation 完成)都会立即断开连接。

是否等待以

更简洁的方式关闭服务主机?也就是说,我想禁用服务侦听器,但也要等待所有当前连接的客户端完成(或指定最大超时)。

WCF 关闭服务主机时等待操作完成

我很惊讶调用ServiceHost.Close不会让LongRunningOperation完成。

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

此方法会导致 通信对象优雅地 从任何状态转换,除了 关闭状态,进入关闭状态 州。关闭方法允许任何 之前要完成的未完成工作 返回。

此外,服务主机上还有一个关闭超时,正是为此。您是否尝试过将关闭超时设置为大于 20 秒?(根据Reflector,ServiceHost的默认关闭超时是10秒...

原则上,我认为以下内容应该是可能的,尽管我尚未实现它以确认所有细节:

  • 实现自定义 IOperationInvoker包装调度程序的法线操作调用程序(您需要一个IServiceBehavior在构建服务调度程序运行时时安装包装的调用程序)
  • 自定义调用程序将主要委托给真正的调用程序,但也将提供"看门人"功能可转身离开当服务主机处于要关闭。
  • 它还将跟踪仍在进度并设置上次操作调用完成或超时时的事件。
  • 然后,主宿主线程将在调用 serviceHost.Close() 之前等待调用程序的"全部完成"事件。

你正在做的事情对我来说似乎都是错误的。服务主机不应突然关闭。这是一项服务,应保持可用。没有客户的参与,就没有真正的方法可以优雅地关闭。当我优雅地说接近时,从客户的角度来看,这也是主观的。

所以我认为我根本不了解您的要求,但是一种方法是实现发布/订阅模式,当主机准备好关闭时,通知所有订阅者此事件,以便每个客户端都可以关闭所有连接。您可以在此处阅读有关此内容的更多信息 http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

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

您正在描述客户端功能。听起来您应该包装服务主机对象,然后在代理"关闭"时拒绝新请求。在处理完所有呼叫之前,不会关闭真正的服务主机。

您还应该查看异步 CTP。将这种逻辑放在消费者端的"Task"对象中,使用即将推出的 TaskCompletionSource 类会容易得多。

从 dnrtv 查看此视频。这不是关于 wcf,而是关于即将推出的异步语言和类支持。