Асинхронный метод Silverlight (возможная ошибка?) - PullRequest
2 голосов
/ 03 сентября 2010

Я работаю над проектом Silverlight 4 «Доказательство концепции» и изучаю путь ASYNC.Я прекратил бороться с желанием внедрить некоторую псевдосинхронную технику дыма и зеркал.Я собираюсь научиться перестать беспокоиться и любить ASYNC.

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

Когда это взорвется мне в лицо или украдет мою жену или свидание с одной из моих дочерей?Есть ли лучший способ сделать это?

Код:

public class CustomPage : Page
{
    static readonly object _AsyncMethodChain_Lock = new object();
    private Dictionary<Action<object>, string> _AsyncMethodChain = new Dictionary<Action<object>, string>();

    public Dictionary<Action<object>, string> AsyncMethodChain
    {
        get { lock (_AsyncMethodChain_Lock) { return this._AsyncMethodChain; } }
        set { lock (_AsyncMethodChain_Lock) { this._AsyncMethodChain = value; } }
    }

    private void CustomPage_Loaded(object sender, RoutedEventArgs e)
    {
        if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
        {
            var user = this.SecurityProvider.UserObject as TimeKeeper.UserServiceReference.User;

            if (user == null)
                return;

            this.AsyncMethodChain.Add(
                data =>
                {
                    var userServiceClient = new UserServiceClient();
                    userServiceClient.GetCompleted +=
                        (send, arg) =>
                        {
                            var userViewSource = this.Resources["userViewSource"] as CollectionViewSource;
                            userViewSource.Source = new List<UserServiceReference.User>(new UserServiceReference.User[1] { arg.Result });
                            userViewSource.View.MoveCurrentToPosition(0);
                            this.AsyncMethodChain.ExecuteNext(arg.Result.UserID, this.BusyIndicator);
                        };
                    userServiceClient.GetAsync(user.UserID);
                },
                "Loading user..."
                );

            this.AsyncMethodChain.Add(
                data =>
                {
                    var userID = (int)data;
                    var timeLogServiceClient = new TimeLogServiceClient();
                    timeLogServiceClient.FindByUserIDCompleted +=
                        (send, arg) =>
                        {
                            var timeLogViewSource = this.Resources["timeLogViewSource"] as CollectionViewSource;
                            timeLogViewSource.Source = arg.Result;
                            this.AsyncMethodChain.ExecuteNext(null, this.BusyIndicator);
                        };
                    timeLogServiceClient.FindByUserIDAsync(userID);
                },
                "Loading time logs..."
                );

            this.AsyncMethodChain.ExecuteNext(null, this.BusyIndicator);
        }
    }
}

public static class Extensions
{
    public static void ExecuteNext(this Dictionary<Action<object>, string> methods, object data, BusyIndicator busyIndicator)
    {
        if (methods.Count <= 0)
        {
            busyIndicator.BusyContent = "";
            busyIndicator.IsBusy = false;
            return;
        }
        else
        {
            var method = methods.Keys.ToList<Action<object>>()[0];
            busyIndicator.BusyContent = methods[method];
            busyIndicator.IsBusy = true;
        }

        methods.ExecuteNext(data);
    }

    public static void ExecuteNext(this Dictionary<Action<object>, string> methods, object data)
    {
        var method = methods.Keys.ToList<Action<object>>()[0];
        methods.Remove(method);
        method(data);
    }
}

1 Ответ

1 голос
/ 03 сентября 2010

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

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

...