【问题标题】:Form unresponsive while restoring database恢复数据库时表单无响应
【发布时间】:2010-12-11 19:12:13
【问题描述】:

我正在尝试在 Windows 窗体应用程序中使用 SMO 来恢复 SQL Server 数据库。我的表单有一个按钮 (button1) 和一个文本框 (textBox1)。单击该按钮时,将调用一个函数来检查 SQL Server 实例是否已启动。如果它没有启动,我启动实例并执行恢复。这可行,但是在执行函数时表单没有响应。这是我的代码:

using System;
using System.Windows.Forms;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Wmi;

namespace WindowsFormsApplication7
{    

    delegate void RestoreDatabaseDelegate();

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BeginInvoke(
                new RestoreDatabaseDelegate(RestoreDatabase));
        }

        private void RestoreDatabase()
        {
            //textBox1.Text = "";

            try
            {
                Restore dbRestore = new Restore();
                dbRestore.Database = "Sandbox";
                dbRestore.Devices.Add(
                    new BackupDeviceItem(
                        @"C:\scripts\sandbox.bak", DeviceType.File));

                Service service =
                    new ManagedComputer().Services["MSSQL$SQLEXPRESS2008"];

                if (service.ServiceState == ServiceState.Stopped)
                {
                    service.Start();
                }

                ServerConnection connection =
                    new ServerConnection(@"TEST\SQLEXPRESS2008");
                connection.LoginSecure = true;

                Server server = new Server(connection);
                Database db = server.Databases[dbRestore.Database];

                dbRestore.ReplaceDatabase = true;
                dbRestore.Complete +=
                    new ServerMessageEventHandler(RestoreComplete);
                dbRestore.Information +=
                    new ServerMessageEventHandler(RestoreInformation);

                dbRestore.SqlRestoreAsync(server);
            }
            catch (Exception ex)
            {
                /*textBox1.Text +=
                    (ex.Message + Environment.NewLine);*/
            }
        }

        private void RestoreComplete(
            object sender, ServerMessageEventArgs e)
        {
            /*textBox1.Text += 
                (e.Error.Message + Environment.NewLine);*/
        }

        private void RestoreInformation(
            object sender, ServerMessageEventArgs e)
        {
            /*textBox1.Text += 
                (e.Error.Message + Environment.NewLine);*/
        }
    }
}

有没有办法在恢复(和 SQL Server 实例启动)正在进行时保持表单响应?我做错了什么?

【问题讨论】:

    标签: c# sql-server winforms smo


    【解决方案1】:

    如果 UI 线程被阻塞,则 UI 无法泵送 Windows 消息(因此会显示为无响应)。相反,请查看 BackgroundWorker,它允许轻松地将运行时间较长的任务推送到工作线程(但仍将更新推送到 UI)。

    【讨论】:

    • SqlRestoreAsync 异步执行恢复操作msdn.microsoft.com/en-us/library/…
    • @Jani 阻塞不是很异步 ;-) 但更严重的是,即使 SqlRestoreAsync 没有阻塞,也可能有另一部分功能(例如服务启动)阻塞。
    • 找到根本原因可能比找到解决方法更能启发我们,我认为调用 SqlRestoreAsync 会阻塞主线程。但为什么呢?
    【解决方案2】:

    看看BackgroundWorker 类。它将允许您在另一个线程上执行长时间运行的操作,而不会阻塞 UI 线程。

    【讨论】:

      【解决方案3】:

      AFAIR 在 Application 类中有一个类似 ProcessMessages 的方法,当您的应用程序的所有者进程响应不佳时,您可以使用该方法处理发送到窗口的消息即使您在另一个线程上做某事并且与主线程无关。

      等待更多

      是的,它是Application.DoEvents();

      提升您的进程或主线程(UI 所有者)可能会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-17
        • 2018-12-02
        • 1970-01-01
        • 1970-01-01
        • 2013-03-22
        • 2019-11-04
        相关资源
        最近更新 更多