程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WCF示例(12) - 並發和限流(Concurrent和Throttle)

WCF示例(12) - 並發和限流(Concurrent和Throttle)

編輯:關於.NET

介紹

WCF(Windows Communication Foundation) - 並發(Concurrent):

1、ConcurrencyMode.Single:單線程並發模式。系統自動加鎖,無並發問題

·InstanceContextMode.PerCall:每個線程都會被分配一個新的實例

·InstanceContextMode.PerSession:每個Session被分配一個新的實例,每個Session內同時只會有一個線程操作實例

·InstanceContextMode.Single:唯一實例,並發調用只會有一個線程操作實例

2、ConcurrencyMode.Reentrant:可重入的單線程並發模式。有可重入(回調)操作時,此模式才會生效,從回調返回的線程會進入隊列尾部排隊

·InstanceContextMode.PerCall:每個線程都會被分配一個新的實例,當有回調操作時如果使用Single並發模式的話就會產生死鎖(1、調用服務端;2、回調客戶端;3、返回服務端,1的時候鎖定了,到3的時候就無法執行了,所以死鎖了),此時應該用Reentrant並發模式

·InstanceContextMode.PerSession:每個Session被分配一個新的實例,每個Session內同時只會有一個線程操作實例,Session內可重入

·InstanceContextMode.Single:唯一實例,並發調用只會有一個線程操作實例,全局可重入

3、ConcurrencyMode.Multiple:多線程並發模式。系統不會自動加鎖,有並發問題

·InstanceContextMode.PerCall:每個線程都會被分配一個新的實例,無並發問題

·InstanceContextMode.PerSession:每個Session被分配一個新的實例,每個Session內多線程操作實例的話會有並發問題

·InstanceContextMode.Single:唯一實例,允許多線程並發操作實例,有並發問題

WCF(Windows Communication Foundation) - 限流(Throttle):

  <behaviors>
    <serviceBehaviors>
      <behavior name="BehaviorPerCall">
        <!--httpGetEnabled - 指示是否發布服務元數據以便使用 HTTP/GET 請求進行檢索,如果發布 WSDL,則為 true,否則為 false,默認值為 false-->
        <serviceMetadata httpGetEnabled="true"/>
        <!--maxConcurrentCalls - 服務中同時存在的最大活動消息數,默認值為 16-->
        <!--maxConcurrentInstances - 服務中同時存在的最大服務實例數,默認值為 Int32.MaxValue-->
        <!--maxConcurrentSessions - 服務中同時存在的最大會話數,默認值為 10-->
        <serviceThrottling maxConcurrentCalls="" maxConcurrentInstances="" maxConcurrentSessions="" />
      </behavior>
      <behavior name="BehaviorPerSession">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceThrottling maxConcurrentCalls="" maxConcurrentInstances="" maxConcurrentSessions="" />
      </behavior>
      <behavior name="BehaviorSingle">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceThrottling maxConcurrentCalls="" maxConcurrentInstances="1" maxConcurrentSessions="" />
      </behavior>
    </serviceBehaviors>
  </behaviors>

示例(以ConcurrencyMode.Reentrant為例)

1、服務

IDuplexReentrant.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
  
namespace WCF.ServiceLib.Message
{
  /**//// <summary>
  /// IDuplexReentrant接口(演示ConcurrencyMode.Reentrant)
  /// </summary>
  /// <remarks>
  /// IDuplexReentrantCallback - 回調接口
  /// </remarks>
  [ServiceContract(CallbackContract = typeof(IDuplexReentrantCallback))]
  public interface IDuplexReentrant
  {
    /**//// <summary>
    /// Hello
    /// </summary>
    /// <param name="name">名字</param>
    [OperationContract]
    void HelloDuplexReentrant(string name);
  }
  
  /**//// <summary>
  /// IDuplexReentrant回調接口
  /// </summary>
  public interface IDuplexReentrantCallback
  {
    /**//// <summary>
    /// Hello
    /// </summary>
    /// <param name="name"></param>
    [OperationContract]
    void HelloDuplexReentrantCallback(string name);
  }
}

DuplexReentrant.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
  
namespace WCF.ServiceLib.Message
{
  /**//// <summary>
  /// DuplexReentrant類 (演示ConcurrencyMode.Reentrant)
  /// </summary>
  /// <remarks>
  /// ConcurrencyMode - 獲取或設置一個值,該值指示服務是支持單線程、多線程還是支持可重入調用。默認值為 System.ServiceModel.ConcurrencyMode.Single。
  /// Single - 服務實例是單線程的,且不接受可重入調用。
  /// Reentrant - 服務實例是單線程的,且接受可重入調用。
  /// Multiple - 服務實例是多線程的。
  /// </remarks>
  [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
  public class DuplexReentrant : IDuplexReentrant
  {
    /**//// <summary>
    /// Hello
    /// </summary>
    /// <param name="name">名字</param>
    public void HelloDuplexReentrant(string name)
    {
      // 聲明回調接口
      IDuplexReentrantCallback callback = OperationContext.Current.GetCallbackChannel<IDuplexReentrantCallback>();
  
      // 調用回調接口中的方法
      callback.HelloDuplexReentrantCallback(name);
    }
  }
}

2、宿主

DuplexReentrant.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
  
namespace WCF.ServiceHost2.Message
{
  /**//// <summary>
  /// host WCF.ServiceLib.Message.DuplexReentrant的類
  /// </summary>
  public class DuplexReentrant
  {
    /**//// <summary>
    /// 啟動WCF.ServiceLib.Message.DuplexReentrant服務
    /// </summary>
    public void Launch()
    {
      using (ServiceHost host = new ServiceHost(typeof(WCF.ServiceLib.Message.DuplexReentrant)))
      {
        host.Open();
  
        Console.WriteLine("服務已啟動(WCF.ServiceLib.Message.DuplexReentrant)");
        Console.WriteLine("按<ENTER>停止服務");
        Console.ReadLine();
  
      }
    }
  }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <!--name - 提供服務的類名-->
      <!--behaviorConfiguration - 指定相關的行為配置-->
      <service name="WCF.ServiceLib.Message.DuplexReentrant" behaviorConfiguration="MessageBehavior">
        <!--address - 服務地址-->
        <!--binding - 通信方式-->
        <!--contract - 服務契約-->
        <endpoint address="Message/DuplexReentrant" binding="netTcpBinding" contract="WCF.ServiceLib.Message.IDuplexReentrant" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:12345/Message/DuplexReentrant"/>
            <add baseAddress="net.tcp://localhost:54321/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MessageBehavior">
          <!--httpGetEnabled - 指示是否發布服務元數據以便使用 HTTP/GET 請求進行檢索,如果發布 WSDL,則為 true,否則為 false,默認值為 false-->
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

3、客戶端

DuplexReentrant.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.ServiceModel;
using System.Windows.Forms;
  
namespace Client2.Message
{
  /**//// <summary>
  /// 演示Message.DuplexReentrant的類
  /// </summary>
  public class DuplexReentrant
  {
    /**//// <summary>
    /// Hello
    /// </summary>
    /// <param name="name">名字</param>
    public void HelloDulexReentrant(string name)
    {
      var ct = new Client2.Message.ReentrantCallbackType();
      var ctx = new InstanceContext(ct);
  
      var proxy = new MessageSvc.DuplexReentrant.DuplexReentrantClient(ctx);
  
      proxy.HelloDuplexReentrant(name);
    }
  }
}

ReentrantCallbackType.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
using System.Windows.Forms;
  
namespace Client2.Message
{
  /**//// <summary>
  /// 實現回調接口
  /// </summary>
  /// <remarks>
  /// CallbackBehavior - 在客戶端應用程序中配置回調服務實現
  /// UseSynchronizationContext - 如果對服務的所有調用都必須在 System.Threading.SynchronizationContext 指定的線程上運行,則為 true;否則為false。默認值為 true。
  /// </remarks>
  [System.ServiceModel.CallbackBehavior(UseSynchronizationContext = false)]
  public class ReentrantCallbackType : MessageSvc.DuplexReentrant.IDuplexReentrantCallback
  {
    /**//// <summary>
    /// Hello
    /// </summary>
    /// <param name="name">名字</param>
    public void HelloDuplexReentrantCallback(string name)
    {
      MessageBox.Show("Hello: " + name);
    }
  }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="net.tcp://localhost:54321/Message/DuplexReentrant"
        binding="netTcpBinding" contract="MessageSvc.DuplexReentrant.IDuplexReentrant">
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

運行結果:

單擊"btnDuplexReentrant"按鈕後彈出提示框,顯示"Hello: webabcd"

OK

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved