C# winfrom 调用耗时函数实现进度条问题(加急)

时间:2021-08-01 01:00:45
C# winfrom 调用耗时函数 怎么和我的处理数据库方法结合下 
下面一个例子 

  public partial class Form1 : Form
    {
        /// <summary>
        /// 后台线程
        /// </summary>
        private BackgroundWorker bkWorker = new BackgroundWorker();

        /// <summary>
        /// 步进值
        /// </summary>
        private int percentValue = 0;

        public Form1()
        {
            InitializeComponent();

            bkWorker.WorkerReportsProgress = true;
            bkWorker.WorkerSupportsCancellation = true;
            bkWorker.DoWork += new DoWorkEventHandler(DoWork);
            bkWorker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
            bkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            percentValue = 10;
            this.progressBar1.Maximum = 1000;
            // 执行后台操作
            bkWorker.RunWorkerAsync();
        }

        public void DoWork(object sender, DoWorkEventArgs e)
        {
            // 事件处理,指定处理函数
            e.Result = ProcessProgress(bkWorker, e);
        }

        public void ProgessChanged(object sender, ProgressChangedEventArgs e)
        {
            // bkWorker.ReportProgress 会调用到这里,此处可以进行自定义报告方式
            this.progressBar1.Value = e.ProgressPercentage;
            int percent = (int)(e.ProgressPercentage / percentValue);
            this.label1.Text = "处理进度:" + Convert.ToString(percent) + "%";
        }

        public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
        {
            this.label1.Text = "处理完毕!";
        }

        private int ProcessProgress(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 1000; i++)
            {
                if (bkWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return -1;
                }
                else
                {
                    // 状态报告
                    bkWorker.ReportProgress(i);

                    // 等待,用于UI刷新界面,很重要
                    System.Threading.Thread.Sleep(1);
                }
            }

            return -1;
        }
    }



   public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public void SetNotifyInfo(int percent, string message)
        {
            this.label1.Text = message;
            this.progressBar1.Value = percent;
        }
    }

以上是网上的调用耗时函数 添加进度条的 的例子。
处理数据库方法 load_cc()  耗时比较大   请问我这个方法应该怎么和这个调用耗时函数结合起来

18 个解决方案

#1


处理数据库方法 load_cc()   这个时间是未知的
一般未知时间等待采用无限等待模式,知道全部完成 才处理

#2


请问哪个是“调用耗时函数”?我看不出来

#3


你的耗时方式写在ProcessProgress函数里,那个for (int i = 0; i <= 1000; i++)就是你实际处理改的逻辑

#4



public partial class Form1 : Form
    {
        private BackgroundWorker bkWorker = new BackgroundWorker();
        private Form2 notifyForm = new Form2();

        public Form1()
        {
            InitializeComponent();

            // 使用BackgroundWorker时不能在工作线程中访问UI线程部分,
            // 即你不能在BackgroundWorker的事件和方法中操作UI,否则会抛跨线程操作无效的异常
            // 添加下列语句可以避免异常。
            CheckForIllegalCrossThreadCalls = false;

            bkWorker.WorkerReportsProgress = true;
            bkWorker.WorkerSupportsCancellation = true;
            bkWorker.DoWork += new DoWorkEventHandler(DoWork);
            bkWorker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
            bkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            notifyForm.StartPosition = FormStartPosition.CenterParent;

            bkWorker.RunWorkerAsync();
            notifyForm.ShowDialog();
        }

        public void DoWork(object sender, DoWorkEventArgs e)
        {
            // 事件处理,指定处理函数
            e.Result = ProcessProgress(bkWorker, e);
        }

        public void ProgessChanged(object sender, ProgressChangedEventArgs e)
        {
            // bkWorker.ReportProgress 会调用到这里,此处可以进行自定义报告方式
            notifyForm.SetNotifyInfo(e.ProgressPercentage, "处理进度:" + Convert.ToString(e.ProgressPercentage) + "%");
        }

        public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
        {
            notifyForm.Close();
            MessageBox.Show("处理完毕!");
        }

        private int ProcessProgress(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 1000; i++)
            {
                if (bkWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return -1;
                }
                else
                {
                    // 状态报告
                    bkWorker.ReportProgress(i / 10);

                    // 等待,用于UI刷新界面,很重要
                    System.Threading.Thread.Sleep(1);
                }
            }

            return -1;
        }
    }


是这个 调用 from2 

#5


// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊

#6


引用 5 楼 starfd 的回复:
// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊


处理数据的方法里面  包含修改和添加 查询 大概耗时在2分钟左右 

#7


引用 1 楼 wangjun8868 的回复:
处理数据库方法 load_cc()   这个时间是未知的
一般未知时间等待采用无限等待模式,知道全部完成 才处理



能给个“无限等待模式”例子看下? 

#8


所谓的无限等待就是开个动态图,让它在哪里动啊动,等你的后台处理完了,再移除(关闭)这个图片

#9


引用 5 楼 starfd 的回复:
// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊


能给具体说下怎么按批量设置这个 i 值 

#10


所谓的批量就是假如你操作100条数据,然后每次都只执行一条,那么你就是设置max为100,i用于记录已经执行了多少条,然后每执行结束一条i就加1

#11


引用 10 楼 starfd 的回复:
所谓的批量就是假如你操作100条数据,然后每次都只执行一条,那么你就是设置max为100,i用于记录已经执行了多少条,然后每执行结束一条i就加1

我这个方法中有 三个 foreach 分别不同的添加修改操作,我这个应该怎么和这个上面的例子结合起来

#12


你三个是操作是并行的(多线程)?还是串行的(单线程)?
单线程就是简单的数字相加汇总,多线程要看你具体怎么写的

#13


引用 12 楼 starfd 的回复:
你三个是操作是并行的(多线程)?还是串行的(单线程)?
单线程就是简单的数字相加汇总,多线程要看你具体怎么写的


三个是串行的单线程,一个执行完 在执行另一个

#14


那你按每个操作步骤汇总呗
比如
List<a> a;
List<b> b;
List<c> c;
int total = a.Count+b.Count+c.Count;
int num=0;
foreach(var i in a)
{
  num++;//然后调用通知
}
foreach(var i in b)
{
  num++;//然后调用通知
}

#15


引用 14 楼 starfd 的回复:
那你按每个操作步骤汇总呗
比如
List<a> a;
List<b> b;
List<c> c;
int total = a.Count+b.Count+c.Count;
int num=0;
foreach(var i in a)
{
  num++;//然后调用通知
}
foreach(var i in b)
{
  num++;//然后调用通知
}


我代码也是按照这样来写的 效果还是不理想,进度条始终是 0% 就不动  

#16


写在ProcessProgress函数里,通过for实现;

#17


实在不行你先抛弃其它的,在循环里面每次赋值后调用Applicaion.DoEvents()试试

#18


该回复于2016-03-17 15:37:06被管理员删除

#1


处理数据库方法 load_cc()   这个时间是未知的
一般未知时间等待采用无限等待模式,知道全部完成 才处理

#2


请问哪个是“调用耗时函数”?我看不出来

#3


你的耗时方式写在ProcessProgress函数里,那个for (int i = 0; i <= 1000; i++)就是你实际处理改的逻辑

#4



public partial class Form1 : Form
    {
        private BackgroundWorker bkWorker = new BackgroundWorker();
        private Form2 notifyForm = new Form2();

        public Form1()
        {
            InitializeComponent();

            // 使用BackgroundWorker时不能在工作线程中访问UI线程部分,
            // 即你不能在BackgroundWorker的事件和方法中操作UI,否则会抛跨线程操作无效的异常
            // 添加下列语句可以避免异常。
            CheckForIllegalCrossThreadCalls = false;

            bkWorker.WorkerReportsProgress = true;
            bkWorker.WorkerSupportsCancellation = true;
            bkWorker.DoWork += new DoWorkEventHandler(DoWork);
            bkWorker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
            bkWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            notifyForm.StartPosition = FormStartPosition.CenterParent;

            bkWorker.RunWorkerAsync();
            notifyForm.ShowDialog();
        }

        public void DoWork(object sender, DoWorkEventArgs e)
        {
            // 事件处理,指定处理函数
            e.Result = ProcessProgress(bkWorker, e);
        }

        public void ProgessChanged(object sender, ProgressChangedEventArgs e)
        {
            // bkWorker.ReportProgress 会调用到这里,此处可以进行自定义报告方式
            notifyForm.SetNotifyInfo(e.ProgressPercentage, "处理进度:" + Convert.ToString(e.ProgressPercentage) + "%");
        }

        public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
        {
            notifyForm.Close();
            MessageBox.Show("处理完毕!");
        }

        private int ProcessProgress(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i <= 1000; i++)
            {
                if (bkWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return -1;
                }
                else
                {
                    // 状态报告
                    bkWorker.ReportProgress(i / 10);

                    // 等待,用于UI刷新界面,很重要
                    System.Threading.Thread.Sleep(1);
                }
            }

            return -1;
        }
    }


是这个 调用 from2 

#5


// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊

#6


引用 5 楼 starfd 的回复:
// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊


处理数据的方法里面  包含修改和添加 查询 大概耗时在2分钟左右 

#7


引用 1 楼 wangjun8868 的回复:
处理数据库方法 load_cc()   这个时间是未知的
一般未知时间等待采用无限等待模式,知道全部完成 才处理



能给个“无限等待模式”例子看下? 

#8


所谓的无限等待就是开个动态图,让它在哪里动啊动,等你的后台处理完了,再移除(关闭)这个图片

#9


引用 5 楼 starfd 的回复:
// 状态报告
bkWorker.ReportProgress(i);

不是有这段代码吗?
如果你的sql是批量插入,然后你就可以按批量设置这个i的值了啊


能给具体说下怎么按批量设置这个 i 值 

#10


所谓的批量就是假如你操作100条数据,然后每次都只执行一条,那么你就是设置max为100,i用于记录已经执行了多少条,然后每执行结束一条i就加1

#11


引用 10 楼 starfd 的回复:
所谓的批量就是假如你操作100条数据,然后每次都只执行一条,那么你就是设置max为100,i用于记录已经执行了多少条,然后每执行结束一条i就加1

我这个方法中有 三个 foreach 分别不同的添加修改操作,我这个应该怎么和这个上面的例子结合起来

#12


你三个是操作是并行的(多线程)?还是串行的(单线程)?
单线程就是简单的数字相加汇总,多线程要看你具体怎么写的

#13


引用 12 楼 starfd 的回复:
你三个是操作是并行的(多线程)?还是串行的(单线程)?
单线程就是简单的数字相加汇总,多线程要看你具体怎么写的


三个是串行的单线程,一个执行完 在执行另一个

#14


那你按每个操作步骤汇总呗
比如
List<a> a;
List<b> b;
List<c> c;
int total = a.Count+b.Count+c.Count;
int num=0;
foreach(var i in a)
{
  num++;//然后调用通知
}
foreach(var i in b)
{
  num++;//然后调用通知
}

#15


引用 14 楼 starfd 的回复:
那你按每个操作步骤汇总呗
比如
List<a> a;
List<b> b;
List<c> c;
int total = a.Count+b.Count+c.Count;
int num=0;
foreach(var i in a)
{
  num++;//然后调用通知
}
foreach(var i in b)
{
  num++;//然后调用通知
}


我代码也是按照这样来写的 效果还是不理想,进度条始终是 0% 就不动  

#16


写在ProcessProgress函数里,通过for实现;

#17


实在不行你先抛弃其它的,在循环里面每次赋值后调用Applicaion.DoEvents()试试

#18


该回复于2016-03-17 15:37:06被管理员删除