Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关闭ServiceHost时,WCF等待操作完成_C#_.net_Wcf_Soap - Fatal编程技术网

C# 关闭ServiceHost时,WCF等待操作完成

C# 关闭ServiceHost时,WCF等待操作完成,c#,.net,wcf,soap,C#,.net,Wcf,Soap,我创建了一个WCF SOAP服务器,其操作需要一些时间来执行: [ServiceContract] public interface IMyService { [OperationContract] string LongRunningOperation(); } [ServiceBehavior( ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false,

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

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

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


从dnrtv退房。这不是关于wcf,而是关于即将到来的异步语言和类支持。

我觉得你所做的一切都错了。ServiceHost不应突然关闭。这是一项服务,应保持可用。没有客户的参与,就没有真正的方式优雅地结束。当我说“优雅地结束”时,从客户的角度来看,这也是主观的

因此,我认为我根本不理解您的要求,但是一种方法是实现发布/订阅模式,当主机准备关闭时,通知所有订阅者此事件,以便每个客户端都可以关闭所有连接。你可以在这里阅读更多关于这方面的内容


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

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

  • 实现自定义IOperationInvoker 包装调度程序的正常 OperationInvoker(在构建service dispatcher运行时,您需要一个
    IServiceBehavior
    来安装包装的调用程序)
  • 自定义调用程序主要会委托给真实调用程序,但也会提供 “看门人”功能可关闭 服务主机即将启动时的新请求(例如引发某种异常) 被关闭
  • 它还将跟踪仍在运行的操作调用 在最后一次操作调用完成或超时时进行并设置事件
  • 然后,主宿主线程将在调用
    serviceHost.Close()
    之前等待调用程序的“all finished”事件
      调用ServiceHost时我很惊讶。Close不允许LongRunning操作完成

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

      此方法会导致 优雅地交流对象 从任何状态转换,而不是 关闭状态,进入关闭状态 国家。Close方法允许任何 未完成的工作将在 返回


      此外,ServiceHost上也有一个CloseTimeout用于此目的。您是否尝试将CloseTimeout设置为大于20秒?(根据Reflector,ServiceHost的默认关闭超时为10秒…

      这就是我试图做的:包装服务主机绑定或通道。但我在寻找一种更简单或更好的方法。顺便问一下,为什么您认为它是客户端功能?我无法控制客户端行为(我不开发它们),我只想在服务器端明确退出,首先关闭侦听器,然后等待所有请求完成。同意,WCF服务不应突然关闭自身。该服务是一个简单的无状态请求-回复web服务,在其中,客户端请求购买操作。出于某些原因,我们需要关闭提供此服务的应用程序。如果客户端无法连接到web服务(购买被拒绝),这是可以的,但在关闭时,我们必须等待活动购买完成(这可能只需要几秒钟),同时停止接受新请求。如果可能的话,应该避免在请求等待响应时中断请求。我认为发布/订阅场景应该足够了。一旦准备关闭,就不应再接受订阅,并通知任何现有订阅服务器您正在关闭。这可能伴随着一些超时因素。如果订阅者没有及时响应,那么您可以像以前一样强制解决问题。作为一项服务,您应该保持一致性,如果强制客户端重新连接需要这样做,那么这就是您需要做的。一个编写良好的客户机应该始终假设失败是一个可行的代码路径。我认为pub/sub不适用于basic和wsHttpBinding,因此Chris Dickson的想法似乎更有用——1:这个要求完全合法。想象一下,尝试实现类似于IIS工作进程回收的东西。服务的新实例启动;所有请求都转移到新实例。退出实例必须等待所有正在运行的操作完成后才能关闭。上述发布/订阅设计不符合要求;它仅在服务关闭时通知客户端。这并不能避免停机时间。这正是我尝试的方式。我只是希望有一个更简单的方法。例如,关闭与ServiceHost关联的ChannelListener似乎也会立即关闭所有通道。我希望它只关闭侦听器,而不是活动的频道。通常,频道侦听器是共享的,所以关闭它会关闭所有