使用 C# 在 WCF 中同时访问 PerSession 服务 [英] Accessing PerSession service simultaneously in WCF using C#

查看:36
本文介绍了使用 C# 在 WCF 中同时访问 PerSession 服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1.) 我有一个主要方法 Processing,它将字符串作为参数,并且该字符串包含一些 x 任务.

2.) 我有另一个方法 Status,它通过使用两个变量 TotalTests 和 CurrentTest 来跟踪第一个方法.每次都会在第一种方法(处理)中循环修改.

3.) 当多个客户端并行调用我的 Web 服务以通过传递字符串来调用 Processing 方法时,具有不同任务的处理将花费更多时间.因此,与此同时,客户端将使用第二个线程调用 Web 服务中的 Status 方法以获取第一个方法的状态.

4.) 当第 3 点完成时,所有客户端都应该并行获取变量(TotalTests、CurrentTest),而不会与其他客户端请求混淆.

5.) 当我将所有客户端设为静态时,我在下面提供的代码会混淆所有客户端的变量结果.如果我删除变量的静态,那么客户端只会为这两个变量获取所有 0,而我无法修复它.请看下面的代码.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]公共类 Service1 : IService1{公共 int TotalTests = 0;公共 int CurrentTest = 0;公共字符串处理(字符串 OriginalXmlString){XmlDocument XmlDoc = new XmlDocument();XmlDoc.LoadXml(OriginalXmlString);this.TotalTests = XmlDoc.GetElementsByTagName("TestScenario").Count;//在给定的xml字符串中查找总测试场景的数量this.CurrentTest = 0;而(i<10){++this.CurrentTest;我++;}}公共字符串状态(){返回 (this.TotalTests + ";" + this.CurrentTest);}}

服务器配置

<绑定名称="WSHttpBinding_IService1" closeTimeout="00:10:00"openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"allowCookies="false"><readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/><reliableSessionordered="true" inactivityTimeout="00:10:00"启用=真"/><安全模式=消息"><传输 clientCredentialType="Windows" proxyCredentialType="None"领域=""/><message clientCredentialType="Windows"negotiationServiceCredential="true"algorithmSuite="默认"建立SecurityContext="true"/></安全></binding></wsHttpBinding>

客户端配置

<绑定名称="WSHttpBinding_IService1" closeTimeout="00:10:00"openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"allowCookies="false"><readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/><reliableSessionordered="true" inactivityTimeout="00:10:00"启用=真"/><安全模式=消息"><传输 clientCredentialType="Windows" proxyCredentialType="None"领域=""/><message clientCredentialType="Windows"negotiationServiceCredential="true"algorithmSuite="默认"建立SecurityContext="true"/></安全></binding></wsHttpBinding>

下面提到的是我的客户端代码

class 程序{static void Main(string[] args){Program prog = new Program();线程 JavaClientCallThread = new Thread(new ThreadStart(prog.ClientCallThreadRun));线程 JavaStatusCallThread = new Thread(new ThreadStart(prog.StatusCallThreadRun));JavaClientCallThread.Start();JavaStatusCallThread.Start();}public void ClientCallThreadRun(){XmlDocument doc = new XmlDocument();doc.Load(@"D:\t72CalculateReasonableWithdrawal_Input.xml");布尔错误=假;Service1Client Client = new Service1Client();string temp = Client.Processing(doc.OuterXml, ref error);}public void StatusCallThreadRun(){int i = 0;Service1Client Client = new Service1Client();字符串温度;而 (i <10){temp = Client.Status();线程睡眠(1500);Console.WriteLine("TotalTestScenarios;CurrentTestCase = {0}", temp);我++;}}}

有人可以帮忙吗.

解决方案

首先因为需要同时访问service,service在处理第一个客户端调用(Processing)时,需要将service并发模式改为Multiple.

还要维护每个客户端的处理状态,因此需要将实例上下文模式设置为 PerSession.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode= InstanceContextMode.PerSession)]

<块引用>

注意

  • 默认 InstanceContextMode 为 PerSession
  • 默认并发模式为单一

您可以执行以下操作以确保您的配置与 PerSession InstanceContextMode 兼容,使用此方法,WCF 将在必要时抛出运行时异常

[ServiceContract(SessionMode=SessionMode.Required)]

<块引用>

注意 使用 InstanceContextMode.PerSession,您将为您创建的每个代理获得不同的实例

因此,每个客户端只需要一个Service1Client"实例,您将调用其 Process 方法并从中检索状态.

同样对于虚拟繁重的处理,您可以仅在处理"方法(服务端)中使用 Thread.Sleep(millisecond) 进行测试建议.

对于客户端应用程序,如果要调用Processing"方法,然后使用Status方法检索状态,则需要异步调用Process方法.

1.在solution-explorer中右键服务引用,选择配置服务引用",勾选生成异步操作",点击确定.

2.像这样更改您的客户端代码

static void Main(string[] args){开始处理();状况报告();Console.ReadLine();}静态 ServiceClient Client = new ServiceClient();private static bool Completed = false;public static void StartProcessing(){XmlDocument doc = new XmlDocument();doc.Load(@"D:\t72CalculateReasonableWithdrawal_Input.xml");布尔错误=假;Client.ProcessingCompleted += Client_ProcessingCompleted;Client.ProcessingAsync(doc.OuterXml);Console.WriteLine("处理中...");}静态无效Client_ProcessingCompleted(对象发送者,ProcessingCompletedEventArgs e){//处理完成,取回Processing操作的返回值完成=真;Console.WriteLine(e.Result);}public static void StatusReport(){int i = 0;字符串温度;而(!完成){temp = Client.Status();Console.WriteLine("TotalTestScenarios;CurrentTestCase = {0}", temp);线程睡眠(500);我++;}}

1.) I have a main method Processing, which takes string as an arguments and that string contains some x number of tasks.

2.) I have another method Status, which keeps track of first method by using two variables TotalTests and CurrentTest. which will be modified every time with in a loop in first method(Processing).

3.) When more than one client makes a call parallely to my web service to call the Processing method by passing a string, which has different tasks will take more time to process. so in the mean while clients will be using a second thread to call the Status method in the webservice to get the status of the first method.

4.) when point number 3 is being done all the clients are supposed to get the variables(TotalTests,CurrentTest) parallely with out being mixed up with other client requests.

5.) The code that i have provided below is getting mixed up variables results for all the clients when i make them as static. If i remove static for the variables then clients are just getting all 0's for these 2 variables and i am unable to fix it. Please take a look at the below code.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{
    public int TotalTests = 0;
    public int CurrentTest = 0;

    public string Processing(string OriginalXmlString)
    {
                XmlDocument XmlDoc = new XmlDocument();
                XmlDoc.LoadXml(OriginalXmlString);
                this.TotalTests = XmlDoc.GetElementsByTagName("TestScenario").Count;  //finding the count of total test scenarios in the given xml string
                this.CurrentTest = 0;
                while(i<10)
                {
                        ++this.CurrentTest;
                         i++;
                }
    }

    public string Status()
    {
        return (this.TotalTests + ";" + this.CurrentTest);
    }
}

server configuration

<wsHttpBinding>
    <binding name="WSHttpBinding_IService1" closeTimeout="00:10:00"
      openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
      bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
      messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
      allowCookies="false">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00"
        enabled="true" />
      <security mode="Message">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="Windows" negotiateServiceCredential="true"
          algorithmSuite="Default" establishSecurityContext="true" />
      </security>
    </binding>
  </wsHttpBinding>

client configuration

<wsHttpBinding>
            <binding name="WSHttpBinding_IService1" closeTimeout="00:10:00"
                openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
                bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                    maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="true" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        algorithmSuite="Default" establishSecurityContext="true" />
                </security>
            </binding>
        </wsHttpBinding>

Below mentioned is my client code

class Program
{
static void Main(string[] args)
{
    Program prog = new Program();
    Thread JavaClientCallThread = new Thread(new ThreadStart(prog.ClientCallThreadRun));
    Thread JavaStatusCallThread = new Thread(new ThreadStart(prog.StatusCallThreadRun));
    JavaClientCallThread.Start();
    JavaStatusCallThread.Start();
}

public void ClientCallThreadRun()
{
    XmlDocument doc = new XmlDocument();
    doc.Load(@"D:\t72CalculateReasonableWithdrawal_Input.xml");
    bool error = false;
    Service1Client Client = new Service1Client();
    string temp = Client.Processing(doc.OuterXml, ref error);
}

public void StatusCallThreadRun()
{
    int i = 0;
    Service1Client Client = new Service1Client();
    string temp;
    while (i < 10)
    {
        temp = Client.Status();
        Thread.Sleep(1500);
        Console.WriteLine("TotalTestScenarios;CurrentTestCase = {0}", temp);
        i++;
    }
}
}

Can any one please help.

解决方案

First because you need to access service simultaneously, when service is processing the first client call(Processing), you need to change service concurrency mode to Multiple.

Also you want to maintain each client processing status, so you need to set instance context mode to the PerSession.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode= InstanceContextMode.PerSession)]

Note

  • Default InstanceContextMode is PerSession
  • Default ConcurrencyMode is Single

You can do following to make sure your configuration is compatible with PerSession InstanceContextMode, using this method, WCF will throw a run-time exception if necessary

[ServiceContract(SessionMode=SessionMode.Required)]

Note With InstanceContextMode.PerSession you will get different instance per each proxy that you create

So you need only one instance of "Service1Client" per client, that you will call its Process method and also retrieve status from it.

Also for virtual heavy processing you can use Thread.Sleep(millisecond) for test proposes only in the "Processing" method(Service-Side).

For the client application if you want to call "Processing" method and then using the Status method to retrieve status, you need to call Process method Asynchronously.

1.Right click on the service reference in solution-explorer and choose "Configure Service Reference" then check the "Generate asynchronous operation" and press OK.

2.Change your client code like this

static void Main(string[] args)
{
    StartProcessing();
    StatusReport();

    Console.ReadLine();
}

static ServiceClient Client = new ServiceClient();
private static bool Completed = false;

public static void StartProcessing()
{
    XmlDocument doc = new XmlDocument();
    doc.Load(@"D:\t72CalculateReasonableWithdrawal_Input.xml");
    bool error = false;

    Client.ProcessingCompleted += Client_ProcessingCompleted;
    Client.ProcessingAsync(doc.OuterXml);

    Console.WriteLine("Processing...");
}

static void Client_ProcessingCompleted(object sender, ProcessingCompletedEventArgs e)
{
    // processing is completed, retreive the return value of Processing operation
    Completed = true;
    Console.WriteLine(e.Result);
}

public static void StatusReport()
{
    int i = 0;
    string temp;
    while (!Completed)
    {
        temp = Client.Status();
        Console.WriteLine("TotalTestScenarios;CurrentTestCase = {0}", temp);
        Thread.Sleep(500);
        i++;
    }
}

这篇关于使用 C# 在 WCF 中同时访问 PerSession 服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆