WinForm窗体调用WCF服务窗体卡死问题


在WinForms应用程序中调用WCF(Windows Communication Foundation)服务时,窗体卡死通常是因为服务调用是同步进行的,阻塞了UI线程。为了解决这个问题,你可以考虑将WCF服务调用放在后台线程中执行,这样就不会阻塞UI线程,从而避免窗体卡死。

以下是一个简单的示例,展示如何使用`Task`或`BackgroundWorker`来异步调用WCF服务:

### 使用 `Task` 异步调用


private async void Button_Click(object sender, EventArgs e)
{
    // 禁用按钮,防止重复点击
    button.Enabled = false;

    try
    {
        // 异步调用WCF服务
        var result = await Task.Run(() =>
        {
            // 假设这是你的WCF客户端代理
            using (var client = new YourWcfServiceClient())
            {
                // 调用WCF服务的方法
                return client.YourMethod();
            }
        });

        // 处理结果
        MessageBox.Show("服务调用结果: " + result.ToString());
    }
    catch (Exception ex)
    {
        // 异常处理
        MessageBox.Show("服务调用出错: " + ex.Message);
    }
    finally
    {
        // 重新启用按钮
        button.Enabled = true;
    }
}

### 使用 `BackgroundWorker` 异步调用


private void Button_Click(object sender, EventArgs e)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (senderWorker, eWorker) =>
    {
        try
        {
            // 假设这是你的WCF客户端代理
            using (var client = new YourWcfServiceClient())
            {
                // 调用WCF服务的方法
                var result = client.YourMethod();

                // 这里不能直接更新UI,但可以通过其他方式(如事件)来通知UI线程
                // 例如,可以使用事件或委托来更新UI
            }
        }
        catch (Exception ex)
        {
            // 异常处理,可能需要通过某种方式通知UI线程
        }
    };

    worker.RunWorkerCompleted += (senderWorker, eWorker) =>
    {
        // 这里可以安全地更新UI
        MessageBox.Show("服务调用完成");
    };

    worker.RunWorkerAsync();
}

注意:在`BackgroundWorker`的`DoWork`事件中,你不能直接更新UI控件,因为`DoWork`事件是在后台线程中执行的。如果你需要更新UI,可以在`RunWorkerCompleted`事件中进行,因为该事件是在UI线程中触发的。或者,你可以使用`Control.Invoke`或`Dispatcher.Invoke`(在WPF中)来在UI线程上执行UI更新操作。

以上两种方法都可以有效地解决WinForms窗体在调用WCF服务时卡死的问题。选择哪种方法取决于你的具体需求和偏好。