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

  • 相关阅读:
    简单所以不要忽视,关于 和 程序员应了解的实际应用
    即使用ADO.NET,也要轻量级动态生成更新SQL,比Ormlite性能更高
    即使用ADO.NET,也要轻量级实体映射,比Dapper和Ormlite均快
    如何在前端实现语义缩放(第一步)
    react教程 — 性能优化
    react教程 — 组件
    react教程 — redux
    create-react-app 创建项目 及 配置
    CSS 预处理器
    react 和 vue 对比
  • 原文地址:https://www.cnblogs.com/smile-wei/p/13093729.html
Copyright © 2011-2022 走看看