2012-06-29 2 views
4

1.) У меня есть основной метод Обработка, которая принимает строку в качестве аргумента и эта строка содержит некоторое количество задач.Доступ к службе PerSession одновременно в WCF с использованием C#

2.) У меня есть другой метод Status, который отслеживает первый метод, используя две переменные TotalTests и CurrentTest. который будет изменяться каждый раз с помощью цикла в первом методе (Обработка).

3.) Когда несколько клиентов совершают вызов параллельно с моей веб-службой, чтобы вызвать метод обработки, передав строку, у которой разные задачи, потребуется больше времени для обработки. поэтому в среднем, в то время как клиенты будут использовать второй поток, чтобы вызвать метод Status в веб-сервисе, чтобы получить статус первого метода.

4.) Когда делается точка 3, все клиенты должны получать переменные (TotalTests, CurrentTest) параллельно с тем, чтобы их смешивали с другими клиентскими запросами.

5.) Код, который я привел ниже, приводит к смешению результатов переменных для всех клиентов, когда я делаю их статическими. Если я удаляю static для переменных, то клиенты просто получают все 0 для этих 2 переменных, и я не могу это исправить. Пожалуйста, ознакомьтесь с приведенным ниже кодом.

[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 ---- я модифицировали, как вы предложили. Пожалуйста, взгляните на это. – krishna555

+0

Вы уверены, что ваши привязки включены в сеанс? Пожалуйста, предоставьте конфигурацию клиента и сервера, если нет. Оба звонка за один сеанс? - Предоставьте код клиента. –

+0

@DmitryHarnitski --- предоставил полную дополнительную информацию, которую вы запросили. Пожалуйста, посмотрите – krishna555

ответ

0

PerSession не приведет к тому, что ваши статические переменные не будут распространены между экземплярами объектов. Единственное, что делает контекстный режим PerSession, - это управление временем жизни объекта.

С PerSession WCF не разрушает объект обслуживания до окончания сеанса. Сессия может быть закрыта явно клиентом или таймаутом (по умолчанию 10 минут). Каждый следующий вызов от клиента с тем же идентификатором сеанса будет маршрутизироваться WCF на существующий объект.

Переменные должны быть не статическими, чтобы предотвратить обмен через разные экземпляры службы. Состояние переменных будет поддерживаться WCF до тех пор, пока вы используете InstanceContextMode.PerSession и привязку, поддерживающую сеанс.

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 будет бросать исключение времени выполнения в случае необходимости

[ServiceContract(SessionMode=SessionMode.Required)] 

Примечание С InstanceContextMode.PerSession вы получите другой экземпляр на каждый прокси-сервер, который вы создаете

Так вам нужен только один экземпляр «Service1Client» для каждого клиента, который вы назовете его методом «Метод», а также получите статус из него.

Также для виртуальной тяжелой обработки вы можете использовать Thread.Sleep (миллисекунда) для теста, предлагаемого только в методе «Обработка» (Service-Side).

Для клиентского приложения, если вы хотите вызвать метод «Обработка», а затем используя метод «Статус» для получения статуса, вам необходимо вызвать метод процесса асинхронно.

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

@Beygi ---- Если я делаю только один экземпляр Service1Client для каждого клиента, тогда я не могу заставить потоки работать параллельно. чтобы проверить, получаю ли я правильные вкладыши. – krishna555

+0

@ krishna555 вы можете, я обновлю ответ ... – Beygi

+0

@Beygi ---- спасибо, я буду ждать вашего обновления .. – krishna555

Смежные вопросы