Silverlight - ожидание завершения асинхронного вызова перед возвратом из метода - PullRequest
1 голос
/ 20 июня 2011

У меня есть приложение Silverlight, которое использует службы WCF, а также использует библиотеку Wintellect Power Threading, чтобы обеспечить полное выполнение логики до продолжения приложения.Это достигается путем обратного вызова приложения с использованием делегатов, чтобы оно могло продолжаться после полного завершения вызова службы.

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

Это лучший способ для достижения этой функциональности?Если это так, вот подробности моей реализации, которая не работает правильно.

public class MyHelper
{

    private static Thread _thread;
    private static User _loadedObject;        

    public static GetUser()
    {
        return _loadedObject;
    }

    public static void LoadObject(int userId)
    {
        _loadedObject = null;
        ParameterizedThreadStart ts = new ParameterizedThreadStart(DoWork);           
        _thread = new Thread(ts);
        _thread.Start(userId);

    }

    private static void DoWork(object parameter)
    {            
        var ae = new AsyncEnumerator();
        ae.BeginExecute(DoWorkWorker(ae, Convert.ToInt32(parameter)), ae.EndExecute);    
    }

    private static IEnumerator<Int32> DoWorkWorker(AsyncEnumerator ae, int userId)
    {
        // Create a service using a helper method
        var service = ServiceHelper.GetService<IUserServiceAsync>();
        service.BeginGetUserById(userId, ae.End(), null);
        yield return 1;

        _loadedObject = service.EndGetUserById(ae.DequeueAsyncResult());
        _thread.Abort();
    }
}

Мой метод тогда:

public int GetUser(int userId)
{
    MyHelper.LoadObject(userId);
    User user = MyHelper.GetUser();
    while (user == null)
    {
        Thread.Sleep(1000);
        user = MyHelper.GetUser();
    }
    return user.Id;
 }

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

Ответы [ 3 ]

1 голос
/ 20 июня 2011

Вся конструкция, которую вы используете, не соответствует современным рекомендациям Silverlight. В Silverlight ваши методы доступа к данным (конечно, через WebServices) выполняются асинхронно. Вы не должны проектировать вокруг этого, но адаптировать свой дизайн соответственно.

Однако последовательный вызов служб (который отличается от синхронного) может быть действительным в некоторых сценариях. В этой записи блога я показал, как этого добиться, подписавшись на событие «Завершено» удаленного вызова и тем временем заблокировав пользовательский интерфейс, с которым рабочий процесс выглядит и ощущается как обычные асинхронные вызовы.

1 голос
/ 21 июня 2011

Если вы кодируете интерфейс, созданный для вашей справочной службы, вы можете вызывать методы Begin и End «синхронно» для каждого из ваших служебных вызовов, тогда мы передаем Action<T> для выполнения после End методов завершено. Обратите внимание, что вы должны сделать это от диспетчера. Это очень близко к синхронному вызову, так как код, выполняемый после того, как вызов все еще записан в месте выполнения вызова, и выполняется после завершения сервисного вызова. Однако это включает в себя создание методов-оболочек, но мы также работали над этим, скрывая наши обертки и генерируя их автоматически. Похоже, много работы, но это не так, и в итоге получается более элегантным, чем все обработчики событий и т. Д. Дайте мне знать, если вам нужна дополнительная информация по этому шаблону

1 голос
/ 20 июня 2011

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

Вы можете имитировать синхронный вызов из потока, не являющегося пользовательским интерфейсом, с обратным вызовом в потоке пользовательского интерфейса, но это, вероятно, не то, что вам нужно. Лучше прикусить пулю и заставить логику вашей программы работать с асинхронными вызовами, которые дает Silverlight.

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