2013-10-04 2 views
1

Я создал приложение службы WCF и в основном ничего не менял, кроме имен, контракт по умолчанию существует и содержит метод GetData(Int32), который возвращает строку..NET WCF сгенерированная задача, похоже, фактически не выполняется на другом потоке

Затем я создал WPF клиента приложения нацеливания .NET FW 4.5 так, где я добавить ссылку на службу к указанной службе, я могу выбрать, чтобы включить задачи на основе асинхронного варианта методов контракта в сгенерированном клиенте услуг.

Теперь, когда я пытаюсь использовать службу, как это:

using (var client = new RhaeoServiceClient()) 
    { 
    client.GetDataAsync(17).ContinueWith(t => MessageBox.Show(t.Result)); 
    MessageBox.Show("inb4"); 
    } 

При выполнении из кнопок мыши обработчика, окна киосков, кнопка остается нажатой в течение секунды или около того, а затем "inb4" сообщение показывает, так мне кажется, что задача выполняется на основном потоке и ждет сети, таким образом, замораживает пользовательский интерфейс.

"inb4" не отображается сразу после нажатия кнопки, кажется, что ждать после выполнения задачи, как я уже сказал, секунды или два. После того, как "inb4" показывает, следующее окно сообщения с результатом также показывает, но что смешно для меня, то следующее окно сообщения не ждет меня, чтобы закрыть первый, он просто появляется над первым почти сразу после первого показа ,

Так что это сбивает с толку, потому что это похоже на то, что код продолжения фактически запускается в другом потоке и не волнует, что основной поток блокируется первым полем сообщения. Но как он отображает окно сообщения, которое может отображаться только из потока пользовательского интерфейса (правильно?)?

И почему первое окно сообщения ждет после выполнения задачи, затем показывается, а затем закрывается следующей, не закрывая?

ответ

0

t.Result блокирует вызывающий поток до тех пор, пока Задача не завершится. Вы можете достичь желаемого результата, используя ключевое слово async/await в сочетании с вызовом WCF.

private void button1_Click(object sender, EventArgs e) 
    { 
     CallGetDataAsync(17); 
     MessageBox.Show("inb4"); 
    } 

    private async void CallGetDataAsync(int number) 
    { 
     string result = null; 

     var client = new Service1Client(); 
     try 
     { 
      // After this line, control is returned to the calling method; the ConfigureAwait(true) 
      // explicitly indicates that when execution resumes, it should attempt to marshall back 
      // to the calling thread. If you change it to false, you can see that the subsequent 
      // messagebox does not stop you from interacting with your main form. 
      result = await client.GetDataAsync(number).ConfigureAwait(true); 

      // when the async service call completes, execution will resume here 
      client.Close(); 
     } 
     catch 
     { 
      try 
      { 
       client.Close(); 
      } 
      catch 
      { 
       client.Abort(); 
      } 
      throw; 
     } 

     // display the MessageBox, this should block the UI thread 
     MessageBox.Show(result); 
    } 

Запуск этого против службы, работающей на той же машине, что и клиент, это трудно понять, что происходит, потому что вызов службы WCF будет возвращать достаточно быстро, что ваш «inb4» по-прежнему отображается после того, как результат обслуживания сообщение. Включение задержки в методе пробной службы помогает лучше проиллюстрировать поведение.

public string GetData(int value) 
    { 
     return Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith(_ => string.Format("You entered: {0}", value)).Result; 
    } 

К вашему последнему вопросу, MessageBox может быть вызван фоновым потоком. Тем не менее, он не будет действовать как модальный и блокирует вашу основную форму, если это будет сделано.

+0

Perfect. Большое спасибо! – user2846145