4

1.)メインメソッドProcessingがあります。これは、文字列を引数として取り、その文字列にはx個のタスクが含まれています。

2.)2つの変数TotalTestsとCurrentTestを使用して、最初のメソッドを追跡する別のメソッドStatusがあります。これは、最初のメソッド(処理)でループ内で毎回変更されます。

3.)複数のクライアントが私のWebサービスと並行して呼び出しを行い、異なるタスクを持つ文字列を渡してProcessingメソッドを呼び出す場合、処理に時間がかかります。その間、クライアントは2番目のスレッドを使用してWebサービスのStatusメソッドを呼び出し、最初のメソッドのステータスを取得します。

4.)ポイント番号3が実行されている場合、すべてのクライアントは、他のクライアント要求と混同されることなく、変数(TotalTests、CurrentTest)を並行して取得することになっています。

5.)以下に提供するコードは、すべてのクライアントを静的にすると、すべてのクライアントの変数の結果が混同されます。変数の静的を削除すると、クライアントはこれら2つの変数のすべての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++;
    }
}
}

誰か助けてくれませんか。

4

2 に答える 2

1

まず、サービスに同時にアクセスする必要があるため、サービスが最初のクライアント呼び出し (処理中) を処理しているときに、サービスの同時実行モードを複数に変更する必要があります。

また、各クライアントの処理ステータスを維持したいので、インスタンス コンテキスト モードを PerSession に設定する必要があります。

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

ノート

  • デフォルトの InstanceContextMode は PerSession です
  • デフォルトの ConcurrencyMode は Single です

次のようにして、構成が PerSession InstanceContextMode と互換性があることを確認できます。このメソッドを使用すると、WCF は必要に応じて実行時例外をスローします。

[ServiceContract(SessionMode=SessionMode.Required)]

InstanceContextMode.PerSession を使用すると、作成するプロキシごとに異なるインスタンスが取得されます

そのため、クライアントごとに必要な "Service1Client" のインスタンスは 1 つだけで、その Process メソッドを呼び出して、そこからステータスを取得することもできます。

また、仮想の重い処理の場合、「処理」メソッド(サービス側)でのみテスト提案に Thread.Sleep(millisecond) を使用できます。

クライアント アプリケーションで「Processing」メソッドを呼び出してから、Status メソッドを使用してステータスを取得する場合は、Process メソッドを非同期的に呼び出す必要があります。

1.ソリューション エクスプローラーでサービス参照を右クリックし、[サービス参照の構成] を選択し、[非同期操作の生成] をオンにして [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++;
    }
}
于 2012-06-29T20:25:48.003 に答える
0

PerSession静的変数がオブジェクト インスタンス間で共有されないようにすることはありません。コンテキスト モードが行う唯一のことPerSessionは、オブジェクトの有効期間を制御することです。

セッションが終了するまで、PerSessionWCF はサービス オブジェクトを破棄しません。セッションは、クライアントまたはタイムアウトによって明示的に閉じることができます (デフォルトは 10 分)。同じセッション ID を持つクライアントからの次の呼び出しはすべて、WCF によって既存のオブジェクトにルーティングされます。

異なるサービス インスタンス間での共有を防ぐために、変数は静的であってはなりません。InstanceContextMode.PerSessionセッションを維持するバインディングを使用している限り、変数の状態は WCF によって維持されます。

public int TotalTests = 0;
public int CurrentTest = 0;

SessionMode.Requiredまた、サービスが適切に構成されていることを確認するために契約を追加します。

 [ServiceContract(SessionMode = SessionMode.Required )]
于 2012-06-29T16:34:25.167 に答える