调用webservice时,WPF窗口被锁定。即使是异步运行

时间:2010-05-17 12:57:31

标签: wpf web-services asynchronous

从我的WPF应用程序调用Web服务时遇到了一个大问题。应用程序/窗口将锁定,直到该过程完成。我试图以异步方式运行它,但问题仍然存在。

目前,我正在制作的网络服务电话可以持续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方法包含设置新表单的调用,包括怪物Web服务调用

    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 个答案:

答案 0 :(得分:1)

您正在使用调度程序将方法调用到GUI线程上。这意味着即使你开始使用后台线程,你也会直接切换回GUI线程,因此GUI将无法响应。

您需要让主要工作在后台线程上进行,然后在需要更新进度条时仅使用调度程序切换到GUI线程。

答案 1 :(得分:0)

在我写这篇文章时,我实际上回答了我自己的问题,但我想在写完这篇文章的时候,我也可以发布答案以防其他人需要它。

我意识到导致问题的方法是在调度程序中,它基本上覆盖了主线程,所以即使我正在设置一个漂亮的ascynchronous线程我正在返回并运行主进程基本上是主线程

或者至少这是我的解释,任何进一步的评论都可以帮助我进一步理解。

所以我从ShowForm方法中删除了怪物调用并将其直接放入异步方法和BooYah中!窗口功能是我的。

HTH

答案 2 :(得分:0)

看起来你正在从异步方法(wat?)同步做UI的东西。此外,您的代码过于复杂,您可能会注意到这一点,因为您已经将它与自己融为一体。

我建议大幅简化这一点,主要是通过JUST异步进行Web服务调用,然后从回调中更新UI。一旦你完成了这项工作,你就可以看到所有其他让我的大脑受伤的东西。