如何推进特定操作的进度条(C#)

时间:2018-04-12 11:11:49

标签: c# sql-server winforms progress

我的问题是,我有SQL服务器,我希望当用户备份数据库时,进度条会像REAL备份操作那样前进。

例如,如果我有100个表,那么,对于每个已备份的1个表,进度条应该提前1个。

或者,id并不重要,只需简单地说,进度条就可以正常运行。

谢谢,代码在下面..

try
        {
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.Filter = "Backup (*.bac) | *.bac";
            progressBar1.Visible = true;

            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                conn.Open();
                com = new SqlCommand("BACKUP DATABASE ServerDB TO DISK = '"+saveFile.FileName+"'", conn);
                com.ExecuteNonQuery();
                conn.Close();
                progressBar1.Visible = false;
                MessageBox.Show("Your backup (" + saveFile.FileName + ") has been created successfuly", "Backup done", MessageBoxButtons.OK);
            }
            else
            {
                progressBar1.Visible = false;
            }
        }
        catch(Exception exp)
        {
            MessageBox.Show(exp.ToString());
            conn.Close();
        }

1 个答案:

答案 0 :(得分:1)

Firt,我的一个小小的烦恼是正确的异常处理,你在那里有一些错误:你抓住了Exception。您没有通过finally关闭连接,因此仅在Exception情况下。如果你想避免任何后续问题,你真的需要阅读这个。以下是我经常链接的两篇文章:

至于实际问题:

您只能在不同的操作之间进行进度报告。主要是做你想要的报告水平,方式更麻烦,然后值得。

虽然一些非常新的类确实支持深度进度报告,但对于大多数其他情况,这意味着您必须重新执行现有代码。通常将其逆向工程设计为您想要进行进度报告的最低循环。最重要的是,您需要一些多任务处理方法。虽然没有返回长时间运行的操作,但UI线程上没有其他代码可以运行。包括实际显示任何更新的代码。我曾经为BackgroundWorker写了一些不错的示例代码。它应该让你走上正确的轨道:

#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
    if (!bgwPrim.IsBusy)
    {
        //Prepare ProgressBar and Textbox
        int temp = (int)nudPrim.Value;
        pgbPrim.Maximum = temp;
        tbPrim.Text = "";

        //Start processing
        bgwPrim.RunWorkerAsync(temp);
    }
}

private void btnPrimCancel_Click(object sender, EventArgs e)
{
    if (bgwPrim.IsBusy)
    {
        bgwPrim.CancelAsync();
    }
}

private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
    int highestToCheck = (int)e.Argument;
    //Get a reference to the BackgroundWorker running this code
    //for Progress Updates and Cancelation checking
    BackgroundWorker thisWorker = (BackgroundWorker)sender;

    //Create the list that stores the results and is returned by DoWork
    List<int> Primes = new List<int>();


    //Check all uneven numbers between 1 and whatever the user choose as upper limit
    for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
    {
        //Report progress
        thisWorker.ReportProgress(PrimeCandidate);
        bool isNoPrime = false;

        //Check if the Cancelation was requested during the last loop
        if (thisWorker.CancellationPending)
        {
            //Tell the Backgroundworker you are canceling and exit the for-loop
            e.Cancel = true;
            break;
        }

        //Determin if this is a Prime Number
        for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
        {
            if (PrimeCandidate % j == 0)
                isNoPrime = true;
        }

        if (!isNoPrime)
            Primes.Add(PrimeCandidate);
    }

    //Tell the progress bar you are finished
    thisWorker.ReportProgress(highestToCheck);

    //Save Return Value
    e.Result = Primes.ToArray();
}

private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    pgbPrim.Value = e.ProgressPercentage;
}

private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    pgbPrim.Value = pgbPrim.Maximum;
    this.Refresh();

    if (!e.Cancelled && e.Error == null)
    {
        //Show the Result
        int[] Primes = (int[])e.Result;

        StringBuilder sbOutput = new StringBuilder();

        foreach (int Prim in Primes)
        {
            sbOutput.Append(Prim.ToString() + Environment.NewLine);
        }

        tbPrim.Text = sbOutput.ToString();
    }
    else 
    {
        tbPrim.Text = "Operation canceled by user or Exception";
    }
}
#endregion