• C# 使用委托实现多线程调用窗体的四种方式(转)


    1、方法一:使用线程

         功能描述:在用c#做WinFrom开发的过程中。我们经常需要用到进度条(ProgressBar)用于显示进度信息。这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息)。下面我就简单结合一个我写的例子给大家做一个介绍。

    第一步:设计界面,注意需要引用 using System.Threading;

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
    控件名称分别为:
    progressBar1;label1;textBox1;button1;

    第二步:定义一个代理,用于更新ProgressBar的值(Value)及在执行方法的时候,返回方法的处理信息。

            private delegate void SetPos(int ipos,string vinfo);//代理

    第三步:进度条值更新函数(参数必须跟声明的代理参数一样)

            private void SetTextMesssage(int ipos,string vinfo)
            {
                if (this.InvokeRequired)
                {
                    SetPos setpos = new SetPos(SetTextMesssage);
                    this.Invoke(setpos, new object[] { ipos,vinfo });
                }
                else
                {
                    this.label1.Text = ipos.ToString() + "/1000";
                    this.progressBar1.Value = Convert.ToInt32(ipos);
                    this.textBox1.AppendText(vinfo);
                }
            }

    第四步:函数实现

            private void button1_Click(object sender, EventArgs e)
            {
                Thread fThread = new Thread(new ThreadStart(SleepT));
                fThread.Start();
            }

    第五步:新的线程执行函数:

            private void SleepT()
            {
                for (int i = 0; i < 500; i++)
                {
                    System.Threading.Thread.Sleep(10);
                    SetTextMesssage(100*i/500,i.ToString()+" ");
                }
            }

    程序运行效果图:

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
     
    =========================================================================================
    2、第二种方法:
         功能描述:该种方法通过控件backgroundWorker1实现,进度条。却进度条在一个模板窗体内。
     
    第一步:主窗体设计:
    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华 

     控件名称:

    button1;backgroundWorker1;

    对backgroundWorker1控件,属性设置:

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
     

     第二步:主页面后台代码:

    using System.Threading;//引用空间名称

            private void button1_Click(object sender, EventArgs e)
            {
                this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件

                ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体 
                form.ShowDialog(this);
                form.Close();
            }

            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    MessageBox.Show(e.Error.Message);
                }
                else if (e.Cancelled)
                {
                }
                else
                {
                }
            }
            //你可以在这个方法内,实现你的调用,方法等。
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
                for (int i = 0; i < 100; i++)
                {
                    Thread.Sleep(100);
                    worker.ReportProgress(i);
                    if (worker.CancellationPending)  // 如果用户取消则跳出处理数据代码 
                    {
                        e.Cancel = true;
                        break;
                    }
                }
            }
    分别为button控件和backgroundWorker1控件选好事件。

    第三步:设置子窗体(及显示进度条的窗体):

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
    控件名称:
    progressBar1;button1
     
    第四步:子窗体,后台代码:

             private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体)

            public ProcessForm(BackgroundWorker backgroundWorker1)
            {
                InitializeComponent();

                this.backgroundWorker1 = backgroundWorker1;
                this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
                this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            }

            void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                //this.Close();//执行完之后,直接关闭页面
            }

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

            private void button1_Click(object sender, EventArgs e)
            {
                this.backgroundWorker1.CancelAsync();
                this.button1.Enabled = false;
                this.Close();
            }
        }

    只为button选好事件
     

    执行效果为:

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华

     =================================================================================================

    3、第三种方法:

         功能描述:在处理大量数据的时候,有时候方法的执行需要一定的时间,这时候往往会造成页面或程序的“假死”状态,给用户的体验度也不是很好。为了避免出现“假死”提高用户的体验度,在这里为这类型的方法加了一个进度条和一个文本框,进度条用于显示程序处理的进度,文本框用于显示在处理过程中,给与的提示。本方法主要使用了控件:backgroundWorker1;说明:本方法与上面的方法(方法二)基本类型,主要是设计和代码进行了一些修改。


     第一步:主窗体设计:
    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华 

    控件名称:

    button1;backgroundWorker1;

    对backgroundWorker1控件,属性设置:


    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华

    第二步:主窗体 后台代码:

            private void button1_Click(object sender, EventArgs e)
            {
                this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件

                ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体 
                form.ShowDialog(this);
                form.Close();
            }

            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    MessageBox.Show(e.Error.Message);
                }
                else if (e.Cancelled)
                {
                }
                else
                {
                }
            }
            //你可以在这个方法内,实现你的调用,方法等。
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
                for (int i = 0; i < 100; i++)
                {
                    Thread.Sleep(100);
                    worker.ReportProgress(i, i.ToString() + "  你好! "); //注意:这里向子窗体返回信息值,这里是两个值,一个用于进度条,一个用于文本框的。
                    if (worker.CancellationPending)  // 如果用户取消则跳出处理数据代码 
                    {
                        e.Cancel = true;
                        break;
                    }
                }
            }

    第三步:设置子窗体(及显示进度条的窗体):

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华

     控件:

    progressBar1;textBox1;button1

    第四步:子窗体后台代码:

            private BackgroundWorker backgroundWorker1; //ProcessForm 窗体事件(进度条窗体)

            public ProcessForm(BackgroundWorker backgroundWorker1)
            {
                InitializeComponent();

                this.backgroundWorker1 = backgroundWorker1;
                this.backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
                this.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            }

            void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                //this.Close();//执行完之后,直接关闭页面
            }

            void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.progressBar1.Value = e.ProgressPercentage;
                this.textBox1.AppendText(e.UserState.ToString());//主窗体传过来的值,通过e.UserState.ToString()来接受
            }

            private void button1_Click(object sender, EventArgs e)
            {
                this.backgroundWorker1.CancelAsync();
                this.button1.Enabled = false;
                this.Close();
            }

    实现的效果:

    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
    注意:如果在程序为执行完,就点击取消的话,很有可能会报错的,这时候,你就修改一个方法:backgroundWorker1_ProgressChanged
    如下:
            void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                this.progressBar1.Value = e.ProgressPercentage;
                this.textBox1.Text += e.UserState.ToString(); //主窗体传过来的值,通过e.UserState.ToString()来接受
            }
           把这个方法,替换上边的那个方法,就可以了。
    =====================================================================================================
    4、第四种方法:
         功能描述:本方法实现进度条显示,方法执行信息反馈显示。用到的技术点为 线程与代理。
         
        步骤一:添加主页面。
          
    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
     
    控件名称:
    button1;
     
      步骤二:主页面后台代码
            using System.Threading;//引用此命名
     
            //创建代理。
            private Form6 myProcessBar = null;//弹出的子窗体(用于显示进度条)
            private delegate bool IncreaseHandle(int nValue,string vinfo);//代理创建
            private IncreaseHandle myIncrease = null;//声明代理,用于后面的实例化代理
            private int vMax = 100;//用于实例化进度条,可以根据自己的需要,自己改变
     
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thdSub = new Thread(new ThreadStart(ThreadFun));
                thdSub.Start();
            }
            private void ThreadFun()
            {
                MethodInvoker mi = new MethodInvoker(ShowProcessBar);
                this.BeginInvoke(mi);
                Thread.Sleep(100);
                object objReturn = null;
                for (int i = 0; i < vMax; i++)
                {
                    objReturn = this.Invoke(this.myIncrease, new object[] { 2, i.ToString() + " " });
                    Thread.Sleep(50);
                }
            }
            private void ShowProcessBar()
            {
                myProcessBar = new Form6(vMax);
                myIncrease = new IncreaseHandle(myProcessBar.Increase);
                myProcessBar.ShowDialog();
                myProcessBar = null;
            }
     
    步骤三:创建子窗体
    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
     控件名称:
    progressBar1;textBox1
     
    步骤四:子窗体,后台代码
            public Form6(int vMax)
            {
                InitializeComponent();
                this.progressBar1.Maximum = vMax;
            }
            public bool Increase(int nValue,string nInfo)
            {
                if (nValue > 0)
                {
                    if (progressBar1.Value + nValue < progressBar1.Maximum)
                    {
                        progressBar1.Value += nValue;
                        this.textBox1.AppendText(nInfo);
                        Application.DoEvents();
                        progressBar1.Update();
                        progressBar1.Refresh();
                        this.textBox1.Update();
                        this.textBox1.Refresh();
                        return true;
                    }
                    else
                    {
                        progressBar1.Value = progressBar1.Maximum;
                        this.textBox1.AppendText(nInfo);
                        //this.Close();//执行完之后,自动关闭子窗体
                        return false;
                    }
                }
                return false;
            }
     
    执行效果:
    实现winfrom进度条及进度信息提示,winfrom程序假死处理 - china_xuhua - 许华
    https://www.cnblogs.com/xinweichen/p/5665763.html
  • 相关阅读:
    Golang :索引值对的数组
    MySql-BlackHole:黑洞引擎
    golang fmt 中的 Sprintf、Fprintf和 Printf函数
    golang 中的 rune 和 byte
    mysql 全文索引
    Python 原始字符串
    如何给博客园(或者CSDN)设置域名访问
    CPU、内存、磁盘三者的关系
    018.redis 阶段性总结:1T 以上海量数据+10 万以上 QPS 高并发+ 99.99% 高可用
    017.redis 在实践中的一些常见问题以及优化思路(包含 linux 内核参数优化)
  • 原文地址:https://www.cnblogs.com/xihong2014/p/9133580.html
Copyright © 2020-2023  润新知