C#控件之进度条—progressBar及其相关知识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yixiantian7/article/details/10415043

铺垫知识:

多线程编程 ThreadStartParameterizedThreadStart

在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。

他们分别是ThreadStart ()ParameterizedThreadStart()

ThreadStart ()是不带参数的形式

使用的方法:

Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));
nonParameterThread.Start();·········此处括号中没有参数

 ParameterizedThreadStart()是带参数的形式

使用的方法:

Thread parameterThread = new Thread(newParameterizedThreadStart(p.ParameterRun));
parameterThread.Name = "Thread A:";
parameterThread.Start(30);·········此处括号中有参数

 

关于参数的类型:object类型

为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool, byte, char, short, int, float, long, double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在启动方法中进行相应的类型转换。

 

二C#中Invoke的用法

在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。

正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。

而所谓的“一面响应操作,一面添加节点”永远只能是相对的,使 UI 线程的负担不至于太大而已,因为界面的正确更新始终要通过 UI 线程去做,我们要做的事情是在工作线程中包揽大部分的运算,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的了。


Control.Invoke 方法 (Delegate)

在拥有此控件的基础窗口句柄的线程上执行指定的委托。

public Object Invoke( Delegatemethod (委托类型))

参数:method

类型:System.Delegate
包含要在控件的线程上下文中调用的方法的委托。

返回值

类型:System.Object
正在被调用的委托的返回值,或者如果委托没有返回值,则为null。

 

备注

委托类似于 C 或 C++ 语言中的函数指针。委托将对方法的引用封装在委托对象中。然后可以将委托对象传递给调用所引用的方法的代码,随后要在编译时调用的方法可以是未知的。与 C 或 C++ 中的函数指针不同的是,委托是面向对象的、类型安全的和更保险的。

如果当前控件的基础窗口句柄尚不存在,则Invoke方法沿控件的父级链搜索,直到找到具有窗口句柄的控件或窗体为止。如果找不到合适的句柄,Invoke方法将引发异常。在调用过程中引发的异常将传播回调用方。

 

 

Control.BeginInvoke 方法 (Delegate)

public IAsyncResult  BeginInvoke(Delegate method)

参数:method

类型:System.Delegate
对不带参数的方法的委托。

返回值

类型:System.IAsyncResult
一个表示BeginInvoke操作的结果的IAsyncResult

 

备注

可异步调用委托并且此方法立即返回。可以从任何线程(甚至包括拥有该控件句柄的线程)调用此方法。如果控件句柄尚不存在,则此方法沿控件的父级链搜索,直到它找到有窗口句柄的控件或窗体为止。如果找不到合适的句柄,BeginInvoke将引发异常。此委托方法中的异常被视为未捕获的异常,将发送给应用程序的未捕获的异常处理程序。

您可以视需要调用 EndInvoke来检索委托的返回值,但不要求一定这样做。 EndInvoke将一直阻止,直到可以检索返回值。



跨线程调用Windows窗体控件————之进度条

简述一下这个小程序的效果:其实就是一个只能做加法的计算器(太逊了),就是在计算的过程中模拟计算很费时,就有一个进度条不断的走进度,当进度条走

完了,那么就将计算结果显示在结果框中  ,因为计算机是在是太能算了,所以为了能看见进度条一步一步走的样子,所以用了一个循环延时来达到这个效果


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace _44_test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Thread t; //定义线程变量,以备后面使用
        //输入部分
        private void btn_caculate_Click(object sender, EventArgs e)
        {
            if (tb_x.Text == "" || tb_y.Text == "")
            {
                MessageBox.Show("请输入要计算的值");
            }
            this.btn_caculate.Enabled = false;//设置计算按钮可以用
            this.tb_result.Text = string.Empty;//清空文本框中的值

            //启动后台线程,实例化一个calcinpu对象传给线程
            backgroundWorker1.RunWorkerAsync(new CalcInput(
                int.Parse(this.tb_x.Text), int.Parse(this.tb_y.Text)));
        }

        //操作开始在另一个线程上运行的的处理程序
        private void backgroundwork1_DoWork(object sender, DoWorkEventArgs e)
        {

            t = new Thread(new ThreadStart(Helper)); //实例化线程
            t.Start();//启动线程
            CalcInput input = (CalcInput)e.Argument;
            e.Result = input.x + input.y;

        }
        //当线程结束执行下面程序,就是结果填充到结果框中
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.tb_result.Text = e.Result.ToString();
        }


        //*******************跨线程调用控件的相关函数*******************************
        //定制一个委托
        private delegate void Forward();//定义一个线程委托
        //定制一个方法,用于线程的调用
        public void Helper()
        {
            Forward d = new Forward(Threading); //实例化一个委托
            this.Invoke(d); //在拥用此控件的基础窗体句柄的线程上执行指定的委托
        }
        //定制实际上执行进度条前进的方法
        public void Threading()
        {

            // 设置精度条的最小值为1
            progressBar1.Minimum = 1;
            // 设置进度条的最大值为100
            progressBar1.Maximum = 100;
            // 设置进度条的初始值为1
            progressBar1.Value = 1;
            // 设置每次增长的步骤为10
            progressBar1.Step = 10;
            //循环10次 每次增长10 最后正好满了,每增长一次休息300(单位时间)
            for (int i = 0; i < 10; i++)
            {
                progressBar1.PerformStep();
                Thread.Sleep(300);
            }
            t.Abort();//关闭线程
        }
    }
}
相信注释的比较详细,应该能看懂~ 
下面这个就上上面那个程序的界面····实在简单··不好意思大笑


展开阅读全文

没有更多推荐了,返回首页