WPF окна заблокированы при вызове веб-службы. Даже при асинхронном запуске - PullRequest
1 голос
/ 17 мая 2010

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

В настоящее время мой веб-сервис может длиться 45-60 секунд. Он запускает процесс на сервере, чтобы получить большой кусок данных. Поскольку мне потребовалось немного времени, я хотел, чтобы индикатор выполнения двигался неопределенно, чтобы пользователь мог видеть, что приложение не остановилось или что-то еще (вы знаете, как они нетерпеливы).

Итак:

    private void btnSelect_Click(object sender, RoutedEventArgs e)
    {
        wDrawingList = new WindowDrawingList(systemManager);

        AsyncMethodHandler caller = default(AsyncMethodHandler);

        caller = new AsyncMethodHandler(setupDrawingList);

        // open new thread with callback method 
        caller.BeginInvoke((Guid)((Button)sender).Tag, MyAsyncCallback, null);
    }

Нажмите кнопку, и приложение создаст форму, в которую будет отправлено асинхронное содержимое, и настроит асинхронное содержимое, вызывающее асинхронный метод.

    public bool setupDrawingList(Guid ID)
    {
        if (systemManager.set(ID))
        {
            wDrawingList.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
            {
                wDrawingList.ShowForm();
                Hide();
            }));

            return true;
        }

        return false;
    }

Это асинхронный метод. Метод showForm содержит вызовы для настройки новой формы, включая вызов веб-службы monster

    public void MyAsyncCallback(IAsyncResult ar)
    {
        // Because you passed your original delegate in the asyncState parameter of the Begin call, you can get it back here to complete the call.
        MethodDelegate dlgt = (MethodDelegate)ar.AsyncState;

        // Complete the call.
        bool output = dlgt.EndInvoke(ar);

        try
        {
            // Retrieve the delegate. 
            AsyncResult result = (AsyncResult)ar;
            AsyncMethodHandler caller = (AsyncMethodHandler)result.AsyncDelegate;

            // Because this method is running from secondary thread it can never access ui objects because they are created 
            // on the primary thread.

            // Call EndInvoke to retrieve the results. 
            bool returnValue = caller.EndInvoke(ar);

            // Still on secondary thread, must update ui on primary thread 
            UpdateUI(returnValue == true ? "Success" : "Failed");
        }
        catch (Exception ex)
        {
            string exMessage = null;
            exMessage = "Error: " + ex.Message;
            UpdateUI(exMessage);
        }
    }

    public void UpdateUI(string outputValue)
    {
        // Get back to primary thread to update ui 
        UpdateUIHandler uiHandler = new UpdateUIHandler(UpdateUIIndicators);
        string results = outputValue;

        // Run new thread off Dispatched (primary thread) 
        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, uiHandler, results);
    }

    public void UpdateUIIndicators(string outputValue)
    {
        // update user interface controls from primary UI thread
        sbi3.Content = "Processing Completed.";
    }

Любая помощь или теории приветствуются. Я в растерянности.

Заранее спасибо

Ответы [ 3 ]

1 голос
/ 17 мая 2010

Вы вызываете метод в потоке GUI, используя диспетчер. Это означает, что, даже если вы начали в фоновом потоке, вы переключаетесь обратно в поток GUI, чтобы графический интерфейс не мог отвечать.

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

0 голосов
/ 17 мая 2010

Похоже, что вы делаете вещи пользовательского интерфейса синхронно из вашего асинхронного метода (ват?). Кроме того, ваш код слишком сложен, что вы можете заметить, когда с ним связались.

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

0 голосов
/ 17 мая 2010

На самом деле я ответил на свой вопрос, когда писал, но подумал, что, написав его, я могу также написать и ответ, если кому-то еще это понадобится.

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

Или, по крайней мере, это моя интерпретация, любые дальнейшие комментарии, которые помогут мне понять дальше, приветствуются.

Поэтому я удалил вызов monster из метода ShowForm и поместил его прямо в метод async и BooYah! Функциональность окна - моя.

НТН

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