C#

2012-06-29 2 views
4

을 사용하여 WCF에서 PerSession 서비스에 동시에 액세스하기 1.) main 메소드 Processing을 사용합니다.이 메소드는 인수로 문자열을 취하고 그 문자열에는 x 개의 작업이 포함되어 있습니다.C#

2.) 두 가지 변수 인 TotalTests와 CurrentTest를 사용하여 첫 번째 방법을 추적하는 또 다른 메서드 Status가 있습니다. 첫 번째 방법 (처리)의 루프에서 매번 수정됩니다.

3.) 둘 이상의 클라이언트가 웹 서비스에 병렬 처리하여 문자열을 전달하여 Processing 메서드를 호출하면 다른 작업을 처리하는 데 더 많은 시간이 소요됩니다. 따라서 클라이언트는 두 번째 스레드를 사용하여 웹 서비스의 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++; 
    } 
} 
} 

입니다 언급했다.

+0

@Beygi 같은 클라이언트 코드가 ---- 내가 수정 한 2.Change

. 그것을보십시오. – krishna555

+0

바인딩에서 세션을 사용할 수 있습니까? 그렇지 않은 경우 클라이언트와 서버 구성을 모두 제공하십시오. 하나의 세션에서 두 통화를 모두합니까? - 고객 코드를 입력하십시오. –

+0

@DmitryHarnitski --- 요청한 완전한 추가 정보를 제공했습니다. 새로운 클라이언트가 새로운 세션을 사용할 때마다 – krishna555

답변

0

PerSession은 개체 인스턴스간에 정적 변수를 공유하지 않습니다. PerSession 컨텍스트 모드가 수행하는 유일한 작업은 개체 수명을 제어하는 ​​것입니다.

PerSession WCF는 세션이 끝날 때까지 서비스 개체를 파괴하지 않습니다. 세션은 클라이언트 또는 제한 시간 (기본값은 10 분)에 의해 명시 적으로 닫을 수 있습니다. 동일한 세션 ID를 가진 클라이언트로부터의 모든 다음 호출은 WCF에 의해 기존 개체로 라우팅됩니다.

을 서로 다른 서비스 인스턴스간에 공유하지 못하도록하려면 변수가 정적이 아니어야합니다. 변수의 상태는 InstanceContextMode.PerSession을 사용하고 세션을 유지하는 바인딩을 사용하는 한 WCF에 의해 유지됩니다.

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

또한 서비스가 제대로 구성되어 있는지 확인하기 위해 계약을 SessionMode.Required을 추가합니다. 동시에 서비스에 액세스해야하기 때문에 서비스가 첫 번째 클라이언트 호출 (처리)을 처리 할 때

[ServiceContract(SessionMode = SessionMode.Required)] 
+0

당신이 말했듯이 피곤하지만 이번에는 변수 값이 0으로 표시됩니다. – krishna555

1

은 첫째, 당신은 여러에 서비스 동시성 모드를 변경해야합니다.

또한 각 클라이언트 처리 상태를 유지하려는 경우 인스턴스 컨텍스트 모드를 PerSession으로 설정해야합니다.

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

  • 기본 InstanceContextMode가 PerSession 이와입니다
  • 기본 들면, ConcurrencyMode 당신은 구성이 PerSession 이와 호환되어 있는지 확인하기 위해 다음을 수행 할 수 있습니다

싱글 나는 nstanceContextMode,이 방법을 사용하여, WCF는 당신이

그래서 만든 각 프록시마다 다른 인스턴스를 얻을 것이다 InstanceContextMode.PerSession와

[ServiceContract(SessionMode=SessionMode.Required)] 

필요한 경우 런타임 예외가 발생합니다 클라이언트 당 하나의 "Service1Client"인스턴스 만 있으면 Process 메소드를 호출하고 그 메소드에서 상태를 검색 할 수 있습니다.

또한 가상 처리의 경우 "처리"방법 (서비스 측)에서만 테스트 용 Thread.Sleep (밀리 초)를 사용할 수 있습니다.

"처리"메서드를 호출 한 다음 상태 메서드를 사용하여 상태를 검색하려면 클라이언트 응용 프로그램의 경우 Process 메서드를 비동기 적으로 호출해야합니다.

1. 솔루션 탐색기에서 서비스 참조를 마우스 오른쪽 버튼으로 클릭하고 "서비스 참조 구성"을 선택한 다음 "비동기 작업 생성"을 선택하고 확인을 누릅니다. 당신이 제안이

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

@Beygi ---- 만약 내가 클라이언트 당 Service1Client 인스턴스를 하나만하고 있다면, 병렬로 작업하는 스레드를 얻을 수 없습니다. 내가 올바른 출력을 받고 있는지 확인합니다. – krishna555

+0

@ krishna555 당신은 할 수 있습니다. 대답을 업데이트하겠습니다 ... – Beygi

+0

@Beygi ---- 당신의 업데이트를 기다리고 있습니다. .. – krishna555