C#progres bar和后台工作者问题

时间:2018-02-07 15:02:59

标签: c# backgroundworker

我已经审核了类似的问题,但没有找到答案。

1 /我正从我的C#表单运行外部文件。它包含在功能中:

    private void SimulatestartTask()
    {
        System.Diagnostics.Process process = new System.Diagnostics.Process();
        System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
        startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
        startInfo.FileName = "test.exe";
        process.StartInfo = startInfo;
        process.Start();
    }

2 /我的背景工人方法写得像这样:

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {   
SimulatestartTask();

                for (int i = 0; i <= 100; i++)
                {

                    backgroundWorker1.ReportProgress(i);
                }
            }
            catch (Exception exx)
            {
                backgroundWorker1.CancelAsync();
                MessageBox.Show("C Sharp is NOT awesome." + exx);
            }
        }

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

我收到了错误:

  

未处理的类型异常   mscorlib.dll中发生'System.Reflection.TargetInvocationException'

     

线程0x4b5c已退出,代码为0(0x0)。抛出异常:    抛出mscorlib.dll异常中的'System.ArgumentException':    抛出mscorlib.dll异常中的'System.ArgumentException':    mscorlib.dll中的“System.Reflection.TargetInvocationException”

我现在迷路了,有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

您只能报告循环迭代之间的进度。要么需要专门设计的某些代码才能发出这些通知(一些较新的异步调用功能)。或者从头开始将整个代码放到最低的循环中。

我写了一个例子,我可以控制整个代码,所以我可以自由地进行报告:

#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

如果程序是控制台程序,将当前进度写入控制台,则可以使用输入重定向将其读出。但另一方面,你和正在进行的进展之间有两层可以获得任何通知。

Anotehr问题我注意到你是异常处理。你捕获异常,不要让它继续下去,这是异常处理的致命罪。 BGW已经开始关注和暴露DoWork代码中可能发生的任何例外情况。再次这样做 - 特别是通过显示MessageBox - 根本不是一个好主意。以下是我经常在异常处理上链接的两篇文章。你应该适当地阅读它们: