【问题标题】:Wcf Singleton with Single Thread带有单线程的 Wcf 单例
【发布时间】:2013-12-30 04:22:25
【问题描述】:

有人能解释一下,虽然我将 InstanceContextMode 和 ConcurrencyMode 都设置为单一,并且在 ServiceThrottlingBehavior 中将最大并发调用实例和会话设置为 1,但我仍然发现至少有 2 个线程正在处理 wcf 请求?

客户端输出:

Client name :kk Instance:1 Thread:13 Time:2013/12/30 12:17:56
Client name :kk Instance:1 Thread:12 Time:2013/12/30 12:17:57
Client name :kk Instance:1 Thread:13 Time:2013/12/30 12:17:58

服务器代码:

    Uri httpUrl = new Uri("http://localhost:8010/MyService/HelloWorld");

    //Create ServiceHost
    ServiceHost host
    = new ServiceHost(typeof(ClassLibrary1.HelloWorldService), httpUrl);

    //Add a service endpoint
    host.AddServiceEndpoint(typeof(ClassLibrary1.IHelloWorldService)
    , new WSHttpBinding(), "");

    //Enable metadata exchange
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
    {
        MaxConcurrentCalls = 1,
        MaxConcurrentInstances = 1 ,
        MaxConcurrentSessions = 1
    };
    host.Description.Behaviors.Add(smb);
    host.Description.Behaviors.Add(stb);
    //Start the Service
    host.Open();

客户代码:

    ServiceReference1.HelloWorldServiceClient obj = new ServiceReference1.HelloWorldServiceClient();
    for(int i=0;i<15;i++)
    {
       obj.Call(str);
       Thread.Sleep(1000);
    }

服务代码:

[ServiceContract]
public interface IHelloWorldService
{
    [OperationContract(IsOneWay=true)]
    void Call(string ClientName);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class HelloWorldService : IHelloWorldService
{
    public static int i;

    public HelloWorldService()
    {
        i++;
    }
    public void Call(string ClientName)
    {
        Console.WriteLine("Client name :" + ClientName + " Instance:" + i.ToString() + " Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + " Time:" + DateTime.Now.ToString() + "\n\n");
    }

}

【问题讨论】:

  • 你将尝试 thread.abort。
  • 我不确定您的测试是否有效。根据 MSDN,对于 ConcurrencyMode.Single,“当实例为调用提供服务时,附加消息到达,这些消息必须等到服务可用或消息超时。”尝试让服务操作执行长时间运行的操作(或简单地使用Thread.Sleep)。服务很可能能够选择任何可用的线程来处理请求,它一次只能使用一个线程。
  • 无论哪种情况,我仍然认为您可能会看到不同的线程 ID。此外,Console.WriteLine 可能存在一些问题 - 至少,我知道在控制台应用程序中使用 async/await 存在问题。

标签: wcf singleton single-threaded


【解决方案1】:

我不是线程方面的专家,但我会尝试一下并扩展我的 cmets。

根据 MSDN,ConcurrencyMode.Single 表示 The service instance is single-threaded and does not accept reentrant calls. If the InstanceContextMode property is Single, and additional messages arrive while the instance services a call, these messages must wait until the service is available or until the messages time out.

您在每次连续调用之间有 1 秒的延迟调用您的服务。您的输出也显示了这一点 - 每个调用都比前一个调用晚 1 秒。

我相信在这种情况下线程 id 是一个红鲱鱼,因为我希望服务使用线程池中的可用线程。我在文档中没有看到任何保证每次都会使用 same 线程的内容,在我看来这将是一个不合理的期望。

如果您希望从可用线程中获得一个专用线程,我认为您无法做到这一点。如果您希望该服务一次只处理一个请求,那么您拥有它的方式应该这样做。

【讨论】:

  • +1 - 同意 same 线程不需要为所有调用提供服务。一次只需要一个线程。
【解决方案2】:

我同意Tim's answer 的观点,即 same 线程不需要为所有调用提供服务。 ConcurencyMode.Single 只会保证一个线程一次为调用提供服务。

如果出于某种原因您需要 WCF 服务上的线程关联,例如,如果您在 WinForms/WPF 应用程序上运行单例服务并且您希望服务调用仅在 UI 线程上运行 - 那么,您只需必须Open UI 线程上的服务主机。 WCF 是 SynchronizationContext 感知的,并且只会将调用调度到 UI 线程,而不管您的 ConcurrencyMode 是什么。另请参阅ServiceBehavior 属性的UseSynchronizationContext 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    相关资源
    最近更新 更多