WCF Async вызывает опрос или пометку — лучшая практика

#c# #silverlight #wcf #callback #asynchronous

#c# #silverlight #wcf #обратный вызов #асинхронный

Вопрос:

Я работаю над этим проектом Silverlight 3.0, который полностью заполнен асинхронными вызовами веб-службы. На главной странице он извлекает некоторые необходимые данные для корректной работы приложения, используя 3 асинхронных вызова. Прямо сейчас приложение не отключает какие-либо элементы управления при выполнении этих вызовов, что означает, что пользователь может взаимодействовать с ним без этих необходимых данных. Мне нужно отключить всю сетку и только после завершения всех 3 асинхронных вызовов включить сетку.

Какова наилучшая практика для этого.

Это мои вызовы:

 client.GetAllAsync();
client.GetAllCompleted  = new EventHandler<GetAllCompletedEventArgs>(client_GetAllCompleted);

client.GetActualAsync();
client.GetActualCompleted  = new EventHandler<GetActualCompletedEventArgs>(client_GetActualCompleted);

client.GetSomeAsync();
client.GetSomeCompleted  = new EventHandler<GetSomeCompletedEventArgs>(client_GetSomeCompleted);
  

Ответ №1:

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

Обычно я предоставляю интерфейс для всего приложения:

 public interface IAppGlobalState 
{
   void BeginAsync(); 
   void EndAsync(); 
}
  

В реализации я сделаю это:

 public partial class MainShell : UserControl, IAppGlobalState 
{
   private int _queue; 
   private object _mutex = new Object();

   public void BeginASync()
   {
      Monitor.Enter(_mutex);
      if (_queue   == 0)
      {
         VisualStateManager.GoToState(this, "BusyState", true);
      }
      Monitor.Exit(_mutex);
   }

   public void EndAsync()
   {
      Monitor.Enter(_mutex);
      if (--_queue == 0)
      {
         VisualStateManager.GoToState(this, "IdleState", true); 
      }
      Monitor.Exit(_mutex);
   }
}
  

Конечно, если у вас тяжелая многопоточность, вы будете использовать Interlocked для них, но большую часть времени вы будете вызывать его из того же потока. Затем вы просто выполняете:

 GlobalState.BeginAsync();
client.FirstAsyncCall();

GlobalState.BeginAsync();
client.FirstAsyncCall();
  

А затем при возврате просто:

 GlobalState.EndAsync();
  

Если у вас есть вложенные вызовы, без проблем, этот метод их разматывает.

Ответ №2:

  1. Создайте единицу рабочего элемента в вашем silverlight
  2. Этот UOW вызывает событие по завершении
  3. Привяжите это событие к вашему коду GUI
  4. Используйте сигнализацию или простой счетчик в вашей рабочей единице, чтобы вызвать событие «завершено».