请大家看一下这段代码,为什么数据库可以备份成功,但不显示进度?网上查了都说可以显示,我的却不能。
#region 数据库的备份和实时进度显示
        public bool BackupDB(string _strFileName)
        {
            m_tspbProgressBar.Value = 0;// 进度条
            m_tspbProgressBar.Maximum = 100;
            m_tspbProgressBar.Visible = true;
            SQLDMO.SQLServer svr = new SQLDMO.SQLServerClass();
            try
            {
                svr.LoginSecure = false;
                svr.Connect(m_strServerName, m_strUserName, m_strPwd);
                SQLDMO.Backup bak = new SQLDMO.BackupClass();
                bak.Action = 0;
                SQLDMO.BackupSink_PercentCompleteEventHandler pceh = new SQLDMO.BackupSink_PercentCompleteEventHandler(Step);
                bak.PercentComplete += pceh;
                bak.Files = _strFileName;
                bak.Database = m_strDbName;
                bak.Initialize = true;
                bak.SQLBackup(svr);
                return true;
            }
            catch (Exception err)
            {
                throw (new Exception(string.Format("备份数据库失败!\r\n错误信息:{0}", err.Message)));
            }
            finally
            {
                svr.DisConnect();
                m_tspbProgressBar.Visible = false;
            }
        }
        private void Step(string message, int percent)
        {
            m_tspbProgressBar.Value = percent;
            Application.DoEvents();
        }
#endregion

解决方案 »

  1.   

    你应该另开线程去做。
    你把代理,回调了本线程的函数,把UI给阻塞了。你可以试试 BackgroundWorker 组件。http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker(VS.80).aspx
      

  2.   


    new 一个 Thread 是么? * V *
      

  3.   


    对,不过最简单的方法是用 backgroundworker组件
      

  4.   


    现在问题是 用MessageBox显示percent始终为0:
    private void Step(string message, int percent) 
            { 
                m_tspbProgressBar.Value = percent; 
                Application.DoEvents(); 
                MessageBox.Show(percent.ToString());// percent始终为0;
            } 
    percent值为0则不可能带动进度条前进。
      

  5.   

    progressBar.Visible = true; 
    progressBar.Minimum = 0; 
    progressBar.Maximum = 100; 
    progressBar.BackColor = Color.Green; 
    for (int i = 0; i < ds.Tables["表"].Rows.Count; i++) 

    progressBar.Value++; 
    Application.DoEvents(); 
    this.label1.Text = Convert.ToString(progressBar.Value);
     } 
    参考
      

  6.   


    我不明白你为什么要用Messagebox,它的出现将阴塞主线程,倒不是说它始终为零,而是由于它出现了,使得整个过程被它中断了。你可以用其它的办法来显示,不是有一个 progressbar 控件么?用它来显示进度。
      

  7.   

    现在就是用progressbar控件显示,就是显示不了,执行完了progressbar.Value的值还是0,根本没有改变过。
      

  8.   


    这样吧,你单步进去,看看每次该 Step 回调函数执行时,persent 的值是多少。如果没有变化的话,那么就应该是SQLDMO.BackupSink_PercentCompleteEventHandler这一代理的问题,而不是你的问题了。
      

  9.   

    我已经试过了Step回调函数,persent 的值始终为0。
      

  10.   

    我现在是用BackgroundWorker组件另开线程运行,UI并没有阻塞(窗口可以操作),备份也成功。但是:
    Step(string message, int percent)函数的percent值始终为0,测试代码如下:
    private void Step(string message, int percent) 

        //m_tspbProgressBar.Value = percent; // 因为percent值始终为0,进度条无法显示进度,
        m_tspbProgressBar.Value += 10;       // 这样却就可以显示进度,只是假进度条。
        Label1.Text += percent.ToString();   // Label1标签显示结果为“0000000”,在窗口上可以实时的看到一个一个“0”被累加显示,证明percent值始终为0。
        Application.DoEvents(); 

    请各位不要再提醒我用BackgroundWorker组件,或说测试percent值方法不对。
    毛主席说的“没有调查就没有发言权”!热心的朋友最好把这段代码复制到你的程序中运行,看是否有进度显示,解决后再指教,非常感谢!
    注:是SQL Server 2005版本。
      

  11.   

    简单的问题。Label1.Text += percent.ToString();  
    改成this.Text = percent.ToString();  至于原因,较复杂,不赘述了。
      

  12.   


    这样做实在很难理解,备份执行完毕后this.Text="0" 即窗口标题为“0”。又有什么意义?
      

  13.   

    用多线程!
    参考:http://tech.ddvip.com/2008-12/1229332510100151.html
      

  14.   

    多线程我已经用了,为什么还要提醒我用多线程?UI没有阻塞,备份过程中,窗口上的东西都可以点击。
    而且测试percent值实时的显示在窗口标题上为“0000000000”,进度条当然也无法正确显示。
    是不是因为是SQL Server 2005的原因呀?在线等待,如果谁解决了,马上给100分。
      

  15.   

    多线程我已经用了,为什么还要提醒我用多线程?UI没有阻塞,备份过程中,窗口上的东西都可以点击。
    而且测试percent值实时的显示在窗口标题上为“0000000000”,进度条当然也无法正确显示。
    是不是因为是SQL Server 2005的原因呀?在线等待,如果谁解决了,马上给100分。
      

  16.   

    下面代码测试通过,测试项目在这里http://www.brsbox.com/filebox/down/fc/373ced1bf28133a7f36ba80ce67989cf可以下载,VS2008写的.using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;namespace dbBackUp
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
               
            }        string m_strServerName = string.Empty;
            string m_strUserName = string.Empty;
            string m_strPwd = string.Empty;
            string m_strDbName = string.Empty;        public void BackupDB(object FileName)
            {
                string _strFileName = FileName.ToString(); 
                SQLDMO.SQLServer svr = new SQLDMO.SQLServerClass();
                try
                {
                    svr.LoginSecure = false;
                    svr.Connect(m_strServerName, m_strUserName, m_strPwd);
                    SQLDMO.Backup bak = new SQLDMO.BackupClass();
                    bak.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
                    SQLDMO.BackupSink_PercentCompleteEventHandler pceh = new SQLDMO.BackupSink_PercentCompleteEventHandler(Step);
                    bak.PercentComplete += pceh;
                    bak.Files = _strFileName;
                    bak.Database = m_strDbName;
                    bak.BackupSetName = m_strDbName;
                    bak.Initialize = true;
                    bak.SQLBackup(svr);
                  
                }
                catch (Exception err)
                {
                    throw (new Exception(string.Format("备份数据库失败!\r\n错误信息:{0}", err.Message)));
                }
                finally
                {
                    svr.DisConnect();              
                }
            }        private void Step(string message, int percent)
            {
                m_tspbProgressBar.Value  = percent;         
                Application.DoEvents();
            }        private void btnBackUp_Click(object sender, EventArgs e)
            {
                m_strServerName = txtServer.Text;
                m_strUserName = txtUserId.Text;
                m_strPwd = txtPwd.Text;
                m_strDbName = txtDbName.Text;
                string fileName = txtFile.Text;
                m_tspbProgressBar.Value = 0;
                m_tspbProgressBar.Minimum = 0;// 进度条 
                m_tspbProgressBar.Maximum = 100;
                m_tspbProgressBar.Visible = true;
              
                ParameterizedThreadStart  ts = new ParameterizedThreadStart(BackupDB);           
                    
                IAsyncResult result =  this.BeginInvoke(ts, fileName);            while (!result.IsCompleted)
                {
                  Application.DoEvents();
                }            if (result.IsCompleted)
                {
                  m_tspbProgressBar.Visible = false;
                  MessageBox.Show("备份成功","Message");
                }
            }
        }
    }
      

  17.   


    23楼iStarSoft你好!
    我已测试,一样的不行。我的是VS2005+SQL Server 2005。不知道是不是SQL Server 2005的问题。
    我是将你项目中的Form1加入到我项目中进行测试的,“//using System.Linq;不用”也可以运行。
    后来我加入了测试代码:
    private void Step(string message, int percent)
    {
        this.Text += percent.ToString();// 加入代码,让窗口标题显示进度结果
        m_tspbProgressBar.Value  = percent;         
        Application.DoEvents();
    }
    窗口标题显示结果为“Form10000000000”,进度条也没有反映,证明percent值为0。
      

  18.   

    不知道你的代码如何的,关键是这句IAsyncResult result =  this.BeginInvoke(ts, fileName);
      

  19.   

    在Catch那设置个断点,确保你的备份没有错误.
    下载这个http://www.brsbox.com/filebox/down/fc/dcc44f919b7a69dcc737b532614d303f运行下,
    在VS2005 + SQL2005下测试通过,server\uid\pwd\dbname改成你自己的.
      

  20.   

    代码就是你那个Form1窗口,我第1次运行没有做任何修改,不行,所以又加了一条测试代码(注:可以备份成功,但就是percent值始终为0):using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    //using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;namespace Lb090
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
               
            }        string m_strServerName = string.Empty;
            string m_strUserName = string.Empty;
            string m_strPwd = string.Empty;
            string m_strDbName = string.Empty;        public void BackupDB(object FileName)
            {
                string _strFileName = FileName.ToString(); 
                SQLDMO.SQLServer svr = new SQLDMO.SQLServerClass();
                try
                {
                    svr.LoginSecure = false;
                    svr.Connect(m_strServerName, m_strUserName, m_strPwd);
                    SQLDMO.Backup bak = new SQLDMO.BackupClass();
                    bak.Action = SQLDMO.SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
                    SQLDMO.BackupSink_PercentCompleteEventHandler pceh = new SQLDMO.BackupSink_PercentCompleteEventHandler(Step);
                    bak.PercentComplete += pceh;
                    bak.Files = _strFileName;
                    bak.Database = m_strDbName;
                    bak.BackupSetName = m_strDbName;
                    bak.Initialize = true;
                    bak.SQLBackup(svr);
                  
                }
                catch (Exception err)
                {
                    throw (new Exception(string.Format("备份数据库失败!\r\n错误信息:{0}", err.Message)));
                }
                finally
                {
                    svr.DisConnect();              
                }
            }        private void Step(string message, int percent)
            {
                this.Text += percent.ToString();// 加入测试代码,让窗口标题显示进度结果
                m_tspbProgressBar.Value  = percent;         
                Application.DoEvents();
            }        private void btnBackUp_Click(object sender, EventArgs e)
            {
                m_strServerName = txtServer.Text;
                m_strUserName = txtUserId.Text;
                m_strPwd = txtPwd.Text;
                m_strDbName = txtDbName.Text;
                string fileName = txtFile.Text;
                m_tspbProgressBar.Value = 0;
                m_tspbProgressBar.Minimum = 0;// 进度条 
                m_tspbProgressBar.Maximum = 100;
                m_tspbProgressBar.Visible = true;
              
                ParameterizedThreadStart  ts = new ParameterizedThreadStart(BackupDB);           
                    
                IAsyncResult result =  this.BeginInvoke(ts, fileName);            while (!result.IsCompleted)
                {
                  Application.DoEvents();
                }            if (result.IsCompleted)
                {
                  MessageBox.Show("备份成功","Message");
                  m_tspbProgressBar.Visible = false;
                }
            }
        }
    }
      

  21.   

    我晕!还是不行,备份是成功了,但percent值始终为0。
    我的是Windows server 2003服务器,难道是这个原因?
      

  22.   

    你在Step设置断点跟踪下吧,如果percent始终是0,进度条也是不会动的了.
    我的环境是XP+VS2005+sql 2005 EXPRESS,都是测试通过的.
      

  23.   

    29 楼 iStarSoft ,谢谢你的支持,虽然没找出原因,我会给你加10分。
    我的环境是Windows Server 2003+VS2005+SQL Server 2005。
    有谁能够真正解决呀?请指教。
      

  24.   

    private void Step(string message, int percent) 
            { 
                m_tspbProgressBar.Value = percent;  // 理论上要改成委托,不过我试过了即使是委托也不会更新
                Application.DoEvents(); //不用       } 最后我只好加个间隔为500毫秒的Timer过变通了,效果很好,
    一个项目里写好的全段例子,无关的我都注释掉了,        #region void TmiBackup_Click(object sender, EventArgs e) // 备份
             /// <summary>
            /// 备份
             /// </summary>
            /// <param name="sender">按钮本身</param>
            /// <param name="e">按钮参数</param>
            void TmiBackup_Click(object sender, EventArgs e)
            {
    //            if (TvServerDirectories.SelectedNode == null || TvServerDirectories.SelectedNode.Text == DataBaseHost)
    //                return;
    //            frmBackupFileName BackupFileName = new frmBackupFileName();
    //            BackupFileName.FileName = DateTime.Now.ToString(Consts.DATETIME_FILELONGFORMAT);
    //            if (BackupFileName.ShowDialog() != DialogResult.OK)
    //                return;
    //            if (BackupFileName.FileName.Trim() == String.Empty)
    //                return;
    //            CurrentDirectory = TvServerDirectories.SelectedNode.Tag.ToString();
    //            CurrentFileName = BackupFileName.FileName.Trim() + "." 
    //+ Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_DATAFILE_EXT;
    //            if (MessageBox.Show(Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_CONFIRM(CurrentDirectory + CurrentFileName), 
    //String.Empty,
    //                MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
    //                return;
    //            TvServerDirectories.Enabled = false;
    //            ((ToolStripButton)TmiRefresh.Tag).Enabled = false;
    //            ((ToolStripButton)TmiBackup.Tag).Enabled = false;
    //            EdtBackupFiles.Enabled = false;
    //            MoBackupFileInfo.Enabled = false;
    //            MC.SlBackup.Text = Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_START;
    //            MC.TspLoading.Value = 0;
    //            MC.TspLoading.Maximum = 100;
    //            MC.TspLoading.Visible = true;
                ProgressBarValue = 0;
                Timer.Enabled = true;
                BackupThread = new Thread(new ThreadStart(DoBackup));
                BackupThread.IsBackground = true;
                BackupThread.Start();
    //            HelpAgentControl.DoAction(new Consts.SERVICE_HELPAGENT_ACTION_PROCESSING(), false);
            }
            #endregion        #region void DoBackup() // 备份线程
             /// <summary>
            /// 备份线程
             /// </summary>
            void DoBackup()
            {
                // DM 为通用委托方法类 
                Backup BackupDatabase = null;
                SQLServer BackupDatabaseConnection = null;
                try
                {
    //                IsBackuping = true;
    //                HelpAgentControl.DoAction(new Consts.SERVICE_HELPAGENT_ACTION_PROCESSING(), false);
                    BackupDatabase = new BackupClass();
                    BackupDatabaseConnection = new SQLServerClass();
                    BackupDatabaseConnection.LoginSecure = false;
                    BackupDatabaseConnection.Connect(DataBaseHost, UserID, Password);
                    BackupDatabase.Action = SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
                    BackupDatabase.Database = DataBase;
                    String FullFileName = "[" + CurrentDirectory + CurrentFileName + "]";
                    BackupDatabase.Files = @" " + FullFileName;
                    BackupDatabase.BackupSetName = DataBase;
                    BackupDatabase.BackupSetDescription = CurrentFileName;
                    BackupDatabase.Initialize = true;
                    BackupSink_PercentCompleteEventHandler BackupDatabaseProgress = new BackupSink_PercentCompleteEventHandler(SetPercent);
                    BackupDatabase.PercentComplete += BackupDatabaseProgress;
                    BackupDatabase.SQLBackup(BackupDatabaseConnection);
    //                DM.SetTextSafely(MC.SlBackup, Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_END); 
                }
                catch (Exception e)
                {
    //                DM.SetTextSafely(MC.SlBackup, Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_ERROR(e.Message));
    //                DM.SetHintTextSafely(MC.SlBackup, Consts.SERVICE_MONITOR_BACKUPRESTORE_BACKUP_ERROR(e.Message));
                }
                finally
                {
    //                IsBackuping = false;
    //                HelpAgentControl.DoAction(new Consts.SERVICE_HELPAGENT_ACTION_RESETPOSE(), false);
    //                BackupDatabaseConnection.DisConnect();
    //                DM.SetEnabledSafely(TvServerDirectories, true);
    //                DM.SetEnabledSafely(TmiRefresh.Tag, true);
    //                DM.SetEnabledSafely(TmiBackup.Tag, true);
    //                DM.SetEnabledSafely(EdtBackupFiles, true);
    //                DM.SetEnabledSafely(MoBackupFileInfo, true);
    //                DM.SetVisibleSafely(MC.TspLoading, false);
                }
            }
            #endregion         #region void SetPercent(String Message, int Percent) // 设置进度条进度值
             /// <summary>
            /// 设置进度条进度值
             /// </summary>
            /// <param name="Message">消息</param>
            /// <param name="Percent">进度值</param>
            void SetPercent(String Message, int Percent)
            {
                ProgressBarValue = Percent;
            }
            #endregion         #region void Timer_Tick(object sender, EventArgs e) // 设置进度条进度
             /// <summary>
            /// 设置进度条进度
             /// </summary>
            /// <param name="sender">控件本身</param>
            /// <param name="e">控件参数</param>
            void timer_Tick(object sender, EventArgs e)
            {
                MC.TspLoading.Maximum = 100;
                MC.TspLoading.Value = ProgressBarValue;
                if (MC.TspLoading.Value >= MC.TspLoading.Maximum)
                {
                    MC.TspLoading.Visible = false;
                    Timer.Enabled = false;
                }
            }
            #endregion
      

  25.   

    现在问题是Step(string message, int percent)的percent值始终为0。如果percent值始终为0,那么数据库备份进度就无法得知。
    我就奇怪,为什么完全一模一样的程序,在别人的XP系统里percent值不为0,而复制到我的WIN2003系统里percent值就始终为0,数据库却备份成功。
    实在是不明白。有谁可以解开这个迷?谢谢!
      

  26.   

    现在不是线程问题,因为已经用了子线程,而是Step(string message, int percent)的percent值为0的问题。
      

  27.   

    要是只模拟一下进度,就加个计时器,Ticker事件里来个进度+1的方法就行
    我曾经做过一个数据转移的winform,其中的进度条是根据各步骤存储过程返回值控制线程委托回调
    用多线程纯属是让进度条走的看起来比较真实,用不用都可以