• 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; }
            }
        }
    }

    千人.NET交流群:18362376,因为有你,代码变得更简单,加群请输入cnblogs
  • 相关阅读:
    我很高兴,很欣慰:)
    任天堂Wii低价发布 游戏革命今冬开始
    血狮——当年号称已经超越C&C的游戏
    网络游戏《防沉迷系统开发标准(试行)》内容
    经典劣作《大卡车》演示视频
    SANTENDO的大脑训练计划
    linq
    对象构造者
    扩展方法
    隐式类型化本地变量
  • 原文地址:https://www.cnblogs.com/kingkoo/p/1447728.html
Copyright © 2020-2023  润新知