• (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。


    关于多线程执行显示进度条的实例!

    之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白
    今天没事,写了一个小小的实例,很简单,就2个文件
    权当抛砖引玉,希望有更好解决方案的人发表一下意见

    界面上2个控件,一个按钮和一个进度条
    using System;
    using System.Threading;
    using System.Windows.Forms;

    namespace WindowsFormsApplication2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            //线程开始的时候调用的委托
            private delegate void maxValueDelegate(int maxValue);
            //线程执行中调用的委托
            private delegate void nowValueDelegate(int nowValue);

            private void button1_Click(object sender, EventArgs e)
            {
                ThreadMethod method = new ThreadMethod();
                //先订阅一下事件
                method.threadStartEvent += new EventHandler(method_threadStartEvent);
                method.threadEvent += new EventHandler(method_threadEvent);
                method.threadEndEvent += new EventHandler(method_threadEndEvent);

                Thread thread = new Thread(new ThreadStart(method.runMethod));
                thread.Start();
            }

            /// <summary>
            /// 线程完成事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void method_threadEndEvent(object sender, EventArgs e)
            {
                MessageBox.Show("我完成啦!");
            }

            /// <summary>
            /// 线程执行中的事件,设置进度条当前进度
            /// 但是我不能直接操作进度条,需要一个委托来替我完成
            /// </summary>
            /// <param name="sender">ThreadMethod函数中传过来的当前值</param>
            /// <param name="e"></param>
            void method_threadEvent(object sender, EventArgs e)
            {
                int nowValue = Convert.ToInt32(sender);
                nowValueDelegate now = new nowValueDelegate(setNow);
                this.Invoke(now, nowValue);
            }

            /// <summary>
            /// 线程开始事件,设置进度条最大值
            /// 但是我不能直接操作进度条,需要一个委托来替我完成
            /// </summary>
            /// <param name="sender">ThreadMethod函数中传过来的最大值</param>
            /// <param name="e"></param>
            void method_threadStartEvent(object sender, EventArgs e)
            {
                int maxValue = Convert.ToInt32(sender);
                maxValueDelegate max = new maxValueDelegate(setMax);
                this.Invoke(max, maxValue);
            }

            /// <summary>
            /// 我被委托调用,专门设置进度条最大值的
            /// </summary>
            /// <param name="maxValue"></param>
            private void setMax(int maxValue)
            {
                this.progressBar1.Maximum = maxValue;
            }

            /// <summary>
            /// 我被委托调用,专门设置进度条当前值的
            /// </summary>
            /// <param name="nowValue"></param>
            private void setNow(int nowValue)
            {
                this.progressBar1.Value = nowValue;
            }
        }
    }

    另外一个文件

    using System;
    using System.Threading;

    namespace WindowsFormsApplication2
    {
        /// <summary>
        /// 线程处理方法
        /// </summary>
        public class ThreadMethod
        {
            /// <summary>
            /// 线程开始事件
            /// </summary>
            public event EventHandler threadStartEvent;
            /// <summary>
            /// 线程执行时事件
            /// </summary>
            public event EventHandler threadEvent;
            /// <summary>
            /// 线程结束事件
            /// </summary>
            public event EventHandler threadEndEvent;

            public void runMethod()
            {
                int count = 100;      //执行多少次
                threadStartEvent.Invoke(count, new EventArgs());//通知主界面,我开始了,count用来设置进度条的最大值
                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(100);//休息100毫秒,模拟执行大数据量操作
                    threadEvent.Invoke(i, new EventArgs());//通知主界面我正在执行,i表示进度条当前进度
                }
                threadEndEvent.Invoke(new object(), new EventArgs());//通知主界面我已经完成了
            }
        }
    }

    对于“线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。”问题可以使用Invoke等委托解决:

    //线程正在运行时候调用的委托
    private delegate void nowValueDelegate(int nowValue);
    private delegate void nowStatusDelegate(string nowStatus);

    //线程开始的时候调用的委托
    private delegate void startDelegate();
    private delegate void maxValueDelegate(int maxValue);

    //线程结束的时候调用的委托
    private delegate void endDelegate();

    /// <summary>
    /// 被委托调用,专门设置进度条当前值的
    /// </summary>
    /// <param name="nowValue"></param>
    private void setNow(int nowValue)
    {
    this.progressBar1.Value = nowValue;
    lblCurrentAmount.Text = "当前已比对" + nowValue + "条数据";
    }

    /// <summary>
    /// 被委托调用,专门设置进度条最大值
    /// </summary>
    /// <param name="nowValue"></param>
    private void setTotal(int total)
    {
    this.progressBar1.Maximum = total;
    this.lblTotal.Text = "共" + total + "条数据";
    }
    /// <summary>
    /// 被委托调用,专门设置当前状态
    /// </summary>
    /// <param name="nowValue"></param>
    private void setStatus(string nowStatus)
    {
    this.lblCurrentStatus.Text = nowStatus;
    }
    /// <summary>
    /// 当线程执行完毕后被委托调用的方法
    /// </summary>
    /// <param name="nowValue"></param>
    private void EndThread()
    {
    this.panel1.Visible = false;
    }
    /// <summary>
    /// 当线程开始时被委托调用的方法
    /// </summary>
    /// <param name="nowValue"></param>
    private void StartThread()
    {
    this.panel1.Visible = true;
    lblCurrentStatus.Text = "正在查询数据…";
    }

    //进程开始时调用的委托
    startDelegate startThread=new startDelegate(StartThread);
    this.Invoke(startThread);

    //委托设置进度当前状态
    nowStatusDelegate status0 = new nowStatusDelegate(setStatus);
    this.Invoke(status0, "正在查询数据…");
    Application.DoEvents();   //在循环体中即使改变了进度条的相关数值也不能实现刷新(消息队列是循环结束后一起发送出去的),所以利用Application.DoEvents();实现实时发送。

    //委托设置进度当前状态
    nowStatusDelegate status = new nowStatusDelegate(setStatus);
    this.Invoke(status, "正在比对数据…");
    Application.DoEvents();

  • 相关阅读:
    poj 1698 二分图多重匹配
    poj 3207 2-sat
    hdu4932 Miaomiao's Geometry
    hdu4924 Football Manager
    hdu4914 Linear recursive sequence
    hdoj4906 Our happy ending(2014 Multi-University Training Contest 4)
    poj1987 Distance Statistics
    poj3342 Party at Hali-Bula
    C/C++ 调用qsort/sort 对字符数组排序的cmp函数写法
    poj1947 Rebuilding Roads
  • 原文地址:https://www.cnblogs.com/xiaoerlang90/p/4229245.html
Copyright © 2020-2023  润新知