多线程和委托

时间:2021-02-18 20:45:25

th.join();方法

 在哪个线程中执行就会阻塞哪个线程,直到th执行完成后才会继续执行.

 ThreadPool.QueueUserWorkItem 线程池,本身是后台线程.放在不用人为去管它,而且很快就执行完的地方.不用start自动开始执行.

            ThreadPool.QueueUserWorkItem((ob) =>
            {
                for (int i = 0; i < 50; i++)
                {
                    lblist[0].Invoke(new Action(() =>
                    {
                        lblist[0].Text = i.ToString();
                    }));
                    Thread.Sleep(100);
                }
            });

多线程跨线程访问:

                        if (lblist[i].InvokeRequired)//判断是不是要调用Invoke方法(跨线程访问true为要调用,反之……)
                        {
                            //lblist[i].Invoke(new Action<string>(s => { lblist[i].Text = s; }), str);
                            lblist[i].Invoke(new Action(() => { lblist[i].Text = str; }));
                        }
                        else
                        {
                            lblist[i].Text = str;
                        }

多线程同步锁:(独占对象)

                    lock();//只能锁定引用不能锁定值类型,比如可以锁list,数组,静态变量.objet、this.,锁住同一个对象(引用地址)就会互斥.

锁定时要考虑到底要锁什么对象,是为了锁定内容在使用时不被其它多线程修改.

为什么锁不了值型?

如果你传一个值类型,会装箱,下次代码运行到这里,又会装箱,两次不是同一个对象,所以锁不住.

异步委托

            Func<string, string, int> length = (aa, bb) => aa.Length + bb.Length; //声明一个有参数和有返回值的委托
            IAsyncResult cc = length.BeginInvoke("654646", "654654+45", null, null);//异步调用
while (!cc.IsCompleted) { out.text="还没有完成,等待中"};//如果cc.IsCompleted==true那就是执行完了,可以放在特殊的地方确认状态  
            int dd = length.EndInvoke(cc);//等待调用的结果,这里会阻塞主线程,一直在这里等着

带回调的异步委托

            button1.Enabled = false;
            Func<string, string, int> length = ((aa, bb) =>
            {
                Thread.Sleep(2000);
                return aa.Length + bb.Length;
            });
          length.BeginInvoke("654646", "654654+45", Deletgate_Next, length);
MessageBox.Show("这里是主线程");

        public void Deletgate_Next(IAsyncResult o)//回调函数,传回来的是length
        {
            var del = (Func<string, string, int>) o.AsyncState;//将o接口对象转为对应的实例对象
            int value = del.EndInvoke(o);                                 //等待结果
            MessageBox.Show(value.ToString());
            if (button1.InvokeRequired)
            {  button1.Invoke(new Action(() => { button1.Enabled = true; })); }
        }
}//这里的执行流程会是,先调用异步线程,然后主线程继续执行,然后在回调函数里执行异步委托的结果 //下面是使用Action委托

        private void button2_Click(object sender, EventArgs e)
        {
            string srt = "";
            Action<string, string> length = ((aa, bb) =>
            {
                Thread.Sleep(2000);
                srt = aa + bb;
            });
            length.BeginInvoke("546545", "65465w", MyAsyncCallback, length);
            MessageBox.Show("主函数");
        }


        public void MyAsyncCallback(IAsyncResult result)
        {
            Action<string, string> del = (Action<string, string>)result.AsyncState;
            del.EndInvoke(result);
            MessageBox.Show("异步回调函数");
        }

 Parallel下面有三个常用的方法invoke,For和ForEach。

            Thread th=new Thread (()=>{
                Parallel.Invoke(new Action(() =>
                {
                    for (int i = 0; i < 100; i++)
                    {
                        Console.WriteLine(i);
                        Thread.Sleep(1000);
                    }
                }), new Action(() =>
                {
                    for (int i = 100; i < 200; i++)
                    {
                        Console.WriteLine(i);
                        Thread.Sleep(1000);
                    }
                }));
                MessageBox.Show(sw.Elapsed.Seconds.ToString());
                sw.Stop();
            });

//可以样多个方法在最快的时间里所有代码一起执行,可以看出方法是并行执行的,执行效率提高了很多。调度时发现会阻塞主线程,最好配合多线程一起执行.



            Parallel.For(0, 50, new Action<int>(i =>
            {
                lblist[1].Invoke(new Action(() =>
                {
                    // lblist[1].Text = i.ToString();
                    Console.Write(i.ToString()+"\r\n");
                }));
               // Thread.Sleep(1000);
            }));