使用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)]
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);
    }
}

服务器配置

<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>

客户端配置

<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>

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

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++;
    }
}
}

任何人都可以帮忙.

最佳答案
首先,因为您需要同时访问服务,当服务正在处理第一个客户端调用(处理)时,您需要将服务并发模式更改为多个.

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

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

Note

  • Default InstanceContextMode is PerSession
  • Default ConcurrencyMode is Single

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

[ServiceContract(SessionMode=SessionMode.Required)]

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

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

此外,对于虚拟重处理,您可以使用Thread.Sleep(毫秒)仅在“处理”方法(服务端)中进行测试.

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

1.右键单击solution-explorer中的服务引用,选择“Configure Service Reference”,然后选中“Generate asynchronous operation”并按“OK”.

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

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服务 - 代码日志