Лучшие практики для преобразования вызовов WCF в асинхронные вызовы WCF - PullRequest
3 голосов
/ 10 марта 2009

У меня возникают проблемы при попытке преобразовать все мои обычные вызовы WCF в асинхронные вызовы WCF. Я обнаружил, что у меня много кода, и я точно не знаю, как это сделать. Я использовал метод, который нашел здесь , но столкнулся с проблемами, когда мне нужно, чтобы все происходило по порядку.

private void btnSave_Click(object sender, RoutedEventArgs e)
{

  List<Item> itemList = GetList();
  foreach(Item i in itemList)
  {
    DoSomeWork(i);

    if(i.SomeID == 0)
    {      
       DoSomeMoreWork(i);  
    }

    UpdateRecord(i)  // this can't execute until the above code is complete

  }
}

private void DoSomeWork(Item i)
{
  // call async method
}

private void DoSomeMoreWork(i)
{
  // call async method
}

private void UpdateRecord(item i)
{
  // call async method
}

Каков наилучший способ рефакторинга кода для асинхронной работы, или мне нужно полностью переосмыслить свою логику? Нужно ли мне вставлять счетчики и переключатели повсюду, чтобы убедиться, что определенные действия выполнены до того, как будут выполнены другие?

РЕДАКТИРОВАТЬ: причина, по которой я делаю это в ближайшие пару месяцев, мы конвертируем это приложение WPF в Silverlight, для которого требуются асинхронные вызовы. Поэтому я пытаюсь преобразовать наши обычные вызовы WCF в асинхронные в процессе подготовки. Я считаю, что это требует другого мышления.

Ответы [ 6 ]

3 голосов
/ 08 августа 2009

Что бы вы ни делали, я бы сказал, что реальное место, где можно справиться, - это сделать один звонок в службу за единицу, а не 3.

Желательно, если список пунктов невелик, сделать один звонок в сервис со всем списком ...

private void btnSave_Click(object sender, RoutedEventArgs e)
{  
    List<Item> itemList = GetList();  
    foreach(Item i in itemList)  
    {    
        DoAllTheWorkAndUpdate(i);    
    }
}

или ...

private void btnSave_Click(object sender, RoutedEventArgs e)
{  
    List<Item> itemList = GetList();  
    foreach(Item i in itemList)  
    {    
        if(i.Id == 0)
        {
            DoLotsOfWorkAndUpdate(i);
        }
        else
        {
            DoSomeWorkAndUpdate(i);
        }

    }
}

или ...

private void btnSave_Click(object sender, RoutedEventArgs e)
{  
    List<Item> itemList = GetList();  
    DoTheWorkOnTheWholeList(itemList);
}

Другими словами, такое чувство, что некоторые из ваших обязанностей могут быть неуместны - я обычно предпочитаю оказывать услуги, когда я могу сделать им один звонок. Тогда асинхронная природа не имеет значения, потому что вы не выполняете последовательность событий.

2 голосов
/ 11 марта 2009

Взгляните на Ювала Лоуи (автора Программирование служб WCF ) веб-сайт , где приведены примеры достижения асинхронного программирования в WCF. Загрузки бесплатны; Вы просто должны указать свой адрес электронной почты.

1 голос
/ 14 июня 2010

Попробуйте использовать это

http://ayende.com/Blog/archive/2008/03/29/WCF-Async-without-proxies.aspx

подход, который определенно работает.

1 голос
/ 10 марта 2009

Я, возможно, немного озадачен тем, почему вам нужно использовать асинхронные операции WCF, когда вам нужно, чтобы вещи были синхронными внутри цикла.

Если вы просто используете асинхронные методы, чтобы предотвратить зависание пользовательского интерфейса, вы можете просто использовать BackgroundWorker, который поддерживает обновления прогресса, чтобы поддерживать актуальность пользовательского интерфейса, и не использовать вызовы Async WCF.

Вы также должны иметь возможность вызывать различные функции из событий Completed для методов Async.

Просто подключите обработчики событий к завершенным событиям, а затем передайте свой объект Item в качестве параметра userState при запуске асинхронного вызова WCF. Таким образом, вы будете иметь его в качестве параметра при срабатывании каждого из завершенных событий. Таким образом, вы будете выполнять следующий этап обработки только после завершения предыдущего асинхронного вызова.

Я не знаю, действительно ли это отвечает на ваш вопрос.

0 голосов
/ 08 августа 2009

Если вы не используете Silverlight, вы можете заблокировать поток одним методом до тех пор, пока другие методы не завершат работу, используя, скажем, ManualResetEvent. Но это не сработает в Silverlight, так как все вызовы WCF происходят в основном потоке пользовательского интерфейса, поэтому, если вы заблокируете этот поток, все блокируется. Лучше всего сделать что-то вроде этого, используя обратные вызовы:

    public delegate void OperationCallback();

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {

        List<Item> itemList = GetList();
        foreach (Item i in itemList)
        {
            DoSomeWork(i, () =>
            {
                if (i.SomeID == 0)
                {
                    DoSomeMoreWork(i, () =>
                    {
                        UpdateRecord(i);
                    });
                }
                else
                {
                    UpdateRecord(i);
                }
            });

        }
    }

    private void DoSomeWork(Item i, OperationCallback callback)
    {
        // call async method then callback when it completes.
        callback();
    }

    private void DoSomeMoreWork(Item i, OperationCallback callback)
    {
        // call async method, then callback when it completes.
        callback();
    }

    private void UpdateRecord(Item i)
    {
        // call async method
    }

Это, конечно, не так ясно, как синхронная версия, но если вы используете лямбда-выражения в максимально возможной степени, все еще возможно сохранить поток управления достаточно читабельным.

0 голосов
/ 08 июля 2009

Добавьте 2 свойства для Item с именами SomeWorkDone и SomeMoreWorkDone как логические значения. Создайте методы для обработки как DoSomeWorkCompleted, так и DoSomeMoreWorkCompleted. В этих методах установите для соответствующих логических свойств значение true и вызовите UpdateRecord. В UpdateRecord убедитесь, что оба свойства Done имеют значение true, а затем завершите вызовы.

У вас могут возникнуть проблемы с конкуренцией, но это должно помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...