• 黄聪:C# 多线程控制控件实例


    该实例功能为“多线程控制UI控件”,线程函数实现自动加1。界面如下:

     

     

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

    namespace treadTest
    {   
        //定义委托
        public delegate void ListBoxDelegate();
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            //委托处理方法(关联与ListBoxDelegate)
            private void ListBox()
            {
                if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
                {
                    listBox1.Items.Add(++CommonData.num);//则直接进行控件操作,“与UI主线程相关联”
                    listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
                }
                else//如果是在另一线程操作ListBox,则启用委托
                    listBox1.Invoke(new ListBoxDelegate(listShow));
            }
           
            //定义对UI主线程控件的操作,“与AddAuto相关联”。
            private void listShow()
            {
                listBox1.Items.Add(CommonData.num);
                listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
            }
            //定义线程函数
            private void AddAuto()
            {
                while (CommonData.Flag == 0)
                {
                    CommonData.num++;
                    Thread.Sleep(1000);
                    ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
                }
            }
            //在click事件中启动多线程
            private void btnStart_Click(object sender, EventArgs e)
            {
                //线程标志置0,表示开启线程
                CommonData.Flag = 0;
                //定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
                ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);
                //实例化线程
                Thread insertTxt = new Thread(new ThreadStart(mycn));
                //启动线程
                insertTxt.Start();     
            }

            private void btnAbort_Click(object sender, EventArgs e)
            {
                CommonData.Flag = 1;
            }
            private void btnCtrlMain_Click(object sender, EventArgs e)
            {
                ListBox();
            }
            private void btnReset_Click(object sender, EventArgs e)
            {
                CommonData.num = 0;
            }
            private void btnClear_Click(object sender, EventArgs e)
            {
                listBox1.Items.Clear();
            }
            private void btnQuit_Click(object sender, EventArgs e)
            {
                Application.Exit();
            }


        }
       
        //全局变量解决方案
        public class CommonData
        {
            private static int _Flag = 0;
            private static int _num = 0;
            public static int Flag
            {
                get { return _Flag; }
                set { _Flag = value; }
            }
            public static int num
            {
                get { return _num; }
                set { _num = value; }
            }
        }
    }

    总结:

            要使用多线程控制UI控件,必须用委托实现。调用控件的Invoke方法(Invoke方法的参数是一个委托类型的参数)。

    实现步骤:

             1.声明委托。

              2.声明委托处理函数(判断是主线程控制UI控件,还是Invoke(多线程)控制UI控件)。

             3.声明一个线程实例,将线程函数的委托传入ThreadStart()。

             4.开启该线程。

             5.定义该线程函数,欲控制UI控件,则调用第2步的委托处理函数,他将自己判断选择用Invoke。

             6.定义Invoke需要调用的函数(如本例的listShow函数)

    //*********************************************************************************************************************************

          在上例中,只是完成了多线程控制主线程控件的功能,如果能手动和自动同时访问全局变量时,就有可能出现线程不同步的问题。以下主要利用lock线程锁来修改解决方案,使线程同步,注意代码带动的地方。

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

    namespace treadTest
    {   
        //定义委托
        public delegate void ListBoxDelegate();
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            //委托处理方法(关联与ListBoxDelegate)
            private void ListBox()
            {
                if (!listBox1.InvokeRequired)//如果在UI主线程操作ListBox,
                {
                    listBox1.Items.Add(CommonData.plus());//则直接进行控件操作,“与UI主线程相关联”
                    listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
                }
                else//如果是在另一线程操作ListBox,则启用委托
                    listBox1.Invoke(new ListBoxDelegate(listShow));
            }
           
            //定义对UI主线程控件的操作,“与AddAuto相关联”。
            private void listShow()
            {
                listBox1.Items.Add(CommonData.plus());
                listBox1.SelectedItem = listBox1.Items[listBox1.Items.Count - 1];
            }
            //定义线程函数
            private void AddAuto()
            {
                while (CommonData.Flag == 0)
                {
                    Thread.Sleep(1000);
                    ListBox();//不能直接控制UI上的控件,所以用该方法选择使用委托
                }
            }
            //在click事件中启动多线程
            private void btnStart_Click(object sender, EventArgs e)
            {
                //线程标志置0,表示开启线程
                CommonData.Flag = 0;
                //定义 ThreadStart的委托类型的参数,并使该委托指向线程函数
                ListBoxDelegate mycn = new ListBoxDelegate(AddAuto);
                //实例化线程
                Thread insertTxt = new Thread(new ThreadStart(mycn));
                //启动线程
                insertTxt.Start();     
            }

            private void btnAbort_Click(object sender, EventArgs e)
            {
                CommonData.Flag = 1;
            }
            private void btnCtrlMain_Click(object sender, EventArgs e)
            {
                ListBox();
            }
            private void btnReset_Click(object sender, EventArgs e)
            {
                CommonData.num = 0;
            }
            private void btnClear_Click(object sender, EventArgs e)
            {
                listBox1.Items.Clear();
            }
            private void btnQuit_Click(object sender, EventArgs e)
            {
                Application.Exit();
            }
        }
       
        //全局变量解决方案
        public class CommonData
        {
            private static int _Flag = 0;
            private static int _num = 0;
            public static int plus()
            {
                lock (new object())
                {
                    return _num++;
                }
            }
            public static int Flag
            {
                get { return _Flag; }
                set { _Flag = value; }
            }
            public static int num
            {
                get { return _num; }
                set { _num = value; }
            }
        }
    }

  • 相关阅读:
    Ueditor富文本编辑器
    ashx误删后,未能创建类型
    一个菜鸟的ASP.NET观光路线图
    地位尴尬的WebForm、ASP.NET核心知识(10)
    经典排序算法--归并排序
    经典排序算法--快速排序
    经典排序算法--冒泡排序
    经典排序算法--堆排序
    经典排序算法--简单选择排序
    经典排序算法--希尔排序
  • 原文地址:https://www.cnblogs.com/huangcong/p/1697090.html
Copyright © 2020-2023  润新知