zoukankan      html  css  js  c++  java
  • C#winform单线程事例与多线程事例

    通过例子编写,用winform编写的,讲解单线程与多线程使用,用于异步加载数据,界面不会卡死,数据在后台默认加载,给用户更好的体验。稍后会附加完整代码。

    1、先不用线程,显示一个求和,计算过程中要停留1秒后继续计算。如果不用多线程页面就会卡死,直到计算完成后才会响应。一个button按钮,一个label 

    界面:

    代码如下:

      #region 不用线程情况
            private void button1_Click(object sender, EventArgs e)
            {
                //不用线程点击按钮,窗体会卡死,10秒后恢复
                int sum = 0;
                for (int i = 0; i < 10; i++)
                {
                    sum = sum + i;
                    label3.Text = sum.ToString();
                    Thread.Sleep(1000);//休息1秒
                }
            }
            #endregion

    2、用单线程进行处理,单独开启一个进线程启动,进行每个2秒钟进行计数显示,并且窗体不会死。界面是一个button 两个 label。

    界面:

    代码:

        #region 多线程中,单独一个线程运行
            private void btnD_Click(object sender, EventArgs e)
            {
                //多线程中,单独一个进程启动,进行每个2秒钟进行计数显示,并且窗体不会死。
                Thread t = new Thread(new ThreadStart(OneThreadSum));//开启线程
                t.IsBackground = true;//附加主线程,主线程关闭后,子线程也跟着关闭,简单理解就是窗体关闭,启动线程也跟着关闭。
                t.Start();
            }
            private void OneThreadSum()
            {
                try
                {
                    Invoke(this, delegate
                    {
                        //按钮变为灰色 防止按钮多次点击
                        //给控件赋值就需要使用invoke
                        this.btnD.Enabled = false;
                    });
                      
                    for (int i = 0; i < 10; i++)
                    {
                        Invoke(this, delegate
                        {
                            //通过代理赋值,通过这种方式,界面和窗口就不会卡死,窗口先展示出来,然后数据过后加载。
                            //给控件赋值就需要使用invoke
                            label2.Text = i.ToString();
                        });
                        Thread.Sleep(2000);//休息2秒
                    }
                }
                catch (Exception ex)
                {
    
                    throw;
                }
                finally 
                {
                    //给控件赋值就需要使用invoke
                    Invoke(this, delegate
                    {
                        this.btnD.Enabled = true;
                    });
                }
                
            }
            /// <summary>
            /// 在线程中通过代理给控件赋值
            /// </summary>
            /// <param name="col"></param>
            /// <param name="method"></param>
            public void Invoke(Control col, MethodInvoker method)
            {
                if (!col.IsHandleCreated) return;//当前控件是否被创建
                if (col.IsDisposed) return;//当前控件是否被销毁
                if (col.InvokeRequired) col.Invoke(method);//是否允许被请求
                else method();
            }
            #endregion

     3、模拟餐馆来人吃饭,客人来了点菜是一个线程,客人就餐时一个线程,客人结账时一个线程,一共3个线程,各自处理各自的事情,一个客人名称textbox, 一个客人来了button,一个启动初始化按钮,listbox1 代表点餐记录 ,listbox2 代表就餐记录 ,listbox3代表结账记录 。

    界面:

    代码:

         #region 用多线程 不是单独一个线程,以3个线程为例
            //模拟餐馆来人吃饭,客人来了点菜是一个线程,客人吃饭时一个线程,客人结账时一个线程,一共3个线程
    
            private void 启动监听线程_Click(object sender, EventArgs e)
            {
                启动监听线程.Enabled = false;//初始化只允许一次,否则会开启很多线程,所以要灰色
                wait1 = new ManualResetEvent(false);//启动信号,等待着。
                t1 = new Thread(new ThreadStart(F1)) { IsBackground = true };
                t1.Start();//初始化线程t1 点餐线程
    
    
                wait2 = new ManualResetEvent(false);
                t2 = new Thread(new ThreadStart(F2)) { IsBackground = true };
                t2.Start();//初始化线程t2 用餐线程
    
    
                wait3 = new ManualResetEvent(false);
                t3 = new Thread(new ThreadStart(F3)) { IsBackground = true };
                t3.Start();//初始化线程t3 结账线程
            }
            private void 客人来了_Click(object sender, EventArgs e)
            {
                data1.Add(textBox1.Text);//这个时候客人来了,增加到list中。
                wait1.Set();//告诉服务员,客人来了,要开始点餐了。
            }
            private IList data1 = new ArrayList();//存储来客人
            private Thread t1 = null;//点菜线程
            private ManualResetEvent wait1 = null;//信号,相当于服务员,客人来了需要告诉
            private void F1()
            {
                while (true)
                {
                    //2秒钟查询一次。
                    if (wait1.WaitOne(2000, false))
                    {
                        if (data1 == null || data1.Count == 0)
                        {
                            //如果一个人都没有的话,不需要点菜
                            Invoke(this, delegate
                            {
                                listBox1.Items.Add("无客人!");
                            });
                            wait1.Reset();//线程停止,继续等待。
                            continue;//结束本次循环
                        }
                        //程序执行到这里说明有人,客人开始点餐。
                        string r = data1[0] as string;
                        Invoke(this, delegate
                        {
                            listBox1.Items.Add(r + "->开始点餐!");
                        });
                        Thread.Sleep(2000);
    
    
                        data2.Add(r);//增加到用餐list中
                        wait2.Set();//告诉可以开始用餐了。
    
                        data1.RemoveAt(0);//客人从队列中移除
                    }
                }
            }
    
    
            private IList data2 = new ArrayList();//存储用餐人
            private Thread t2 = null;//用餐线程
            private ManualResetEvent wait2 = null;//信号,用餐信号
            private void F2()
            {
                while (true)
                {
                    if (wait2.WaitOne(2000, false))
                    {
                        if (data2 == null || data2.Count == 0)
                        {
                            Invoke(this, delegate
                            {
                                listBox2.Items.Add("无用餐人!");
                            });
                            wait2.Reset();
                            continue;
                        }
                        //程序执行到这里说明有人,客人开始用餐。
                        string r = data2[0] as string;
    
                        Invoke(this, delegate
                        {
                            listBox2.Items.Add(r + "->用餐中...!");
                        });
                        Thread.Sleep(3000);
    
                        data3.Add(r);//增加到结账的list中
                        wait3.Set();//告诉客人可以开始结账了
    
                        data2.RemoveAt(0);//客人从队列中移除
                    }
                }
            }
    
    
            private IList data3 = new ArrayList();//存储结账人
            private Thread t3 = null;//结账线程
            private ManualResetEvent wait3 = null;//结账信号
            private void F3()
            {
                while (true)
                {
                    if (wait3.WaitOne(2000, false))
                    {
                        if (data3 == null || data3.Count == 0)
                        {
                            Invoke(this, delegate
                            {
                                listBox3.Items.Add("无结账人!");
                            });
                            wait3.Reset();
                            continue;
                        }
                        //程序执行到这里说明有人,客人开始结账。
                        string r = data3[0] as string;
    
                        Invoke(this, delegate
                        {
                            listBox3.Items.Add(r + "->结账买单!");
                        });
                        Thread.Sleep(4000);
    
                        data3.RemoveAt(0);//客人从队列中移除
                    }
                }
            }
    
            /// <summary>
            /// 在线程中通过代理给控件赋值
            /// </summary>
            /// <param name="col"></param>
            /// <param name="method"></param>
            public void Invoke(Control col, MethodInvoker method)
            {
                if (!col.IsHandleCreated) return;//当前控件是否被创建
                if (col.IsDisposed) return;//当前控件是否被销毁
                if (col.InvokeRequired) col.Invoke(method);//是否允许被请求
                else method();
            }
    
            #endregion

     csdn 源码下载链接:https://download.csdn.net/download/njxiaogui/12514492

  • 相关阅读:
    jackson 枚举 enum json 解析类型 返回数字 或者自定义文字 How To Serialize Enums as JSON Objects with Jackson
    Antd Pro V5 中ProTable 自定义查询参数和返回值
    ES6/Antd 代码阅读记录
    es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?
    Antd Hooks
    使用.Net Core开发WPF App系列教程(其它 、保存控件内容为图片)
    使用.Net Core开发WPF App系列教程( 三、与.Net Framework的区别)
    使用.Net Core开发WPF App系列教程( 四、WPF中的XAML)
    使用.Net Core开发WPF App系列教程( 二、在Visual Studio 2019中创建.Net Core WPF工程)
    使用.Net Core开发WPF App系列教程( 一、.Net Core和WPF介绍)
  • 原文地址:https://www.cnblogs.com/smile-wei/p/13093729.html
Copyright © 2011-2022 走看看