多线程,匿名委托,异步调用

简单的线程处理 及同步:

public class MuThread
{
    int a = 0;

    int i = 0;
    private volatile bool _run=true;
    public void method(object par)
    {
        while (_run)
        {
            Console.WriteLine("运行中"+par.ToString());
        }
        Console.WriteLine("已结束");
        
    }
    public void stop()
    {
        _run = false;
    }

    public void method1()
    {
        while (a < 100)
        {
            a++; Console.WriteLine("线程1输出:" + a);
        }
    }
    public void method2()
    {
        //当不加入线程同步代码的时候调用method1跟method2 会出现混乱
        //但是通过数他们的输出行数依然是100行 
        //说明while判断是正确的 
        //当CPU分配时间片的时候 无论他们有多么接近 其实同一时间依然只有一个线程在访问变量a

        //但是线程1跟2是CPU随机分配时间片交替前进的 实现同一时间多个进度协同执行任务的效果

        while (a < 100)
        {
            a++; Console.WriteLine("线程2输出:" + a);
        }
    }

    public void methodSyn1()
    {
        while (a < 100)
        {
            lock (this)
            {
                //意思是代码进入lock范围后 大括号内的代码将会被单独占用直到执行完
                //而不会临时被其他时间片插入导致a的值已经更改
                //当时间片继续回到此段时还沿用原来的 变量 导致混乱
                //如果去掉前面的判断 会输出101 ,至于原理么跟孙鑫C++线程同步是一样的 也有Monitor.Entry()
                if (a < 100)
                {
                    a++; Console.WriteLine("线程1输出:" + a);
                }
            }
        }
    }

    public void methodSyn2()
    {
        while (a < 100)
        {
            Monitor.Enter(this);
            if (a < 100)
            {
                a++; Console.WriteLine("线程2输出:" + a);
            }
            Monitor.Exit(this);
        }
    }
}

线程示例:

static void Main()
{
    //Service s = new Service();
    //s.start();

    //初始化MuThread的时候可以在构造函数 中传入一个方法引用也就是delegate
    //然后再MuThread实例的线程方法执行完毕后调用该delegate 
    //这种编程方式我一直认为很高深 被那些砖家称之为"回调"callback
    //参见ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_fxadvance/html/52b32222-e185-4f42-91a7-eaca65c0ab6d.htm
    MuThread m = new MuThread();

    //ThreadStart 其实是一个委托
    //在C++里就需要声明委托 
    //为了给方法传参数但是不能为每种类型都定义一个委托 所以只能传入object类型

    //.Net为我们简化了的语法
    Thread tPar = new Thread(m.method);
    tPar.Start("传入的参数");

    //ParameterizedThreadStart委托显示语法 start()其实相当于Event.do()            
    ParameterizedThreadStart del = new ParameterizedThreadStart(m.method);
    Thread tPar2 = new Thread(del);
    tPar2.Start("传入的参数");

    Thread t = new Thread(new ThreadStart(m.method1));
    Thread t2 = new Thread(new ThreadStart(m.method2));
    t2.Start();
    t.Start();
    //利用volatile 参数的状态终止线程
    while (!tPar.IsAlive) ;

    Thread.Sleep(100);
    m.stop();
    //MSDN的意思是阻断当前调用t的线程 也就是Main 主线程 直到让t执行完毕
    //事实确实是这样的 当不加Join()的时候 看着t.start()的语句在main方法下面的循环语句前面
    //其实他们的时间片依然由CPU随机分配的 "主线程调用"这句输出是穿插在前面子线程输出一起的
    //参见ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/fxref_mscorlib/html/56ed7b6f-efe0-67e7-34bc-766dd9f693f9.htm
    //当主线程 也就是Main方法里进行Thread.Sleep(200)时 其实是挂起主线程 这样就可以把时间片让给那些子线程
    t.Join();
    for (int i = 0; i < 50; i++)
    {
        Console.WriteLine("主线程调用");
    }

    //使用线程池
    //ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_csref/html/5426dae4-c3f3-4e76-a998-19f7ca4baf3f.htm
    Console.ReadKey();
}

 又反复测试了下join其实感觉就像endInvoke 就是阻止,说白了把指定的线程join到当前主线程 说白了就是阻塞操作 可不就是endInvoke么  ,到trd.Join()的 地方位置 必须要等待trd执行完毕

使用backgroundworker组件:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.WorkerSupportsCancellation = true;
        button3.Enabled = false;
    }

    private void button2_Click(object sender, EventArgs e)//start
    {
        textBox1.Text = "开始产生10000以内的随机数。。。\n\n";
        button2.Enabled = false;
        button3.Enabled = true;
        //在后台开始操作
        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        //不要直接使用组件实例名称(backgroundworker1)因为有多个backgroundworker时
        //直接使用会产生耦合问题 应该通过下面的转换使用它
        BackgroundWorker worker = sender as BackgroundWorker;
        //下面的内容相当于线程要处理的内容。//注意 不要在此事件中和界面控件打交道
        Random r = new Random();
        int numCount = 0;
        while (worker.CancellationPending==false)
        {
            int num = r.Next(10000);
            if (num%5==0)
            {
                numCount++;
                worker.ReportProgress(0, num);
                Thread.Sleep(1000);
            }
        }
        e.Result = numCount;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        int num = (int)e.UserState;
        textBox1.Text += num + " ";
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error==null)
        {
            textBox1.Text += "\n\n操作停止,共产生" + e.Result + "个能被5整除的随机数";
        }
        else
        {
            textBox1.Text += "\n操作过程中产生错误:" + e.Error;
        }
    }

    private void button3_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
        button3.Enabled = false;
        button2.Enabled = true;
    }

}

一些关于匿名委托 和lambda表达式的写法 ,还有异步调用:

  1 public void callDel(Func<int,int,int> dd)
  2         {
  3             int rst = dd.Invoke(5, 2);
  4             Console.WriteLine("call Func rst is:{0}", rst);
  5         }
  6 
  7         public int method1()
  8         {
  9             
 10             //delDone.WaitOne(2000);
 11             Thread.Sleep(2000);
 12             
 13             return 1;
 14         }
 15 
 16         public delegate int MyDele();
 17 ManualResetEvent delDone = new ManualResetEvent(false);
 18         private void Form3_Load(object sender, EventArgs e)
 19         {
 20 
 21             //waitone的作用 仅仅是阻断当前行代码以后的部分继续执行
 22             //然后在回调里证明已经回调已经完成了  继续放行
 23             //实际上是一种失去异步意义的一种方式 ,线程同步
 24             delDone.Reset();
 25             MyDele d4 = new MyDele(method1);
 26             d4.BeginInvoke((iar) =>
 27             {
 28                 int rdmResult = d4.EndInvoke(iar);
 29                 Console.WriteLine("iar call back state :" + iar.AsyncState.ToString());
 30                 Console.WriteLine("iar call back rst is :{0}", rdmResult);
 31                 delDone.Set();
 32             }, "ss");
 33             //delDone.Set();
 34             delDone.WaitOne(1000);
 35             Console.WriteLine("lalalala....");
 36 
 37             return;//----------------------------------------------------------------------------------------------------
 38             var cl = new {name="xiang",age=21};
 39             Console.WriteLine(cl.name);
 40             return;//-----------------------------------------------------------------------------------------------------
 41             //调用func  调用func 的直接好处就是 让你连委托声明 那句都省了
 42             //说白了就是你传一段代码进来 我来执行 ,那么你传的这段代码就是参数 。你只需要把方法原型作为形参定义好
 43             //感觉完全一锅写 有点类似于脚本语言的写法
 44             //上面是lambda写法 下面是 匿名委托写法
 45             callDel((num1, num2) => {
 46                 return num1 + num2;
 47             });
 48             callDel((num1, num2) => {
 49                 return num1 - num2;
 50             });
 51 
 52             callDel(delegate (int num1, int num2) {
 53                 return num1 * num2;
 54             });
 55 
 56             MyDele d2 = delegate ()
 57             {
 58                 Console.WriteLine("call myDel2....");
 59                 return 0;
 60             };
 61             d2();
 62 
 63             MyDele d3 = new MyDele(
 64             delegate {
 65                 Console.WriteLine("call myDel3....");
 66                 return 0;
 67             });
 68             d3();
 69 
 70             return;//-----------------------------------------------------------------------------------------------
 71             //异步回调
 72             MyDele d1 = new MyDele(() => {
 73                 //MessageBox.Show("mydel process");
 74                 Console.WriteLine("mydel start");
 75                 Thread.Sleep(2000);
 76                 Console.WriteLine("mydel end");
 77                 return new Random().Next();
 78             });
 79             //d1.Invoke();
 80 
 81             IAsyncResult iars= d1.BeginInvoke((iar) =>
 82             {
 83                 //委托内容执行完成 后的回调
 84 
 85                 //iar 可以理解为特定的线程的句柄 进行回溯的 找到我们当初调用的 那个方法
 86                 //从而获取到 方法执行的结果 ,endinvolve 代表实质性的异步调用结束 可获得实实在在的执行结果
 87                 //既然执行到这里了 那么自然代表可以正常endinvoke了。
 88                 int rdmResult = d1.EndInvoke(iar);
 89                 Console.WriteLine("iar call back state :" + iar.AsyncState.ToString());
 90                 Console.WriteLine("iar call back rst is :{0}",rdmResult);
 91             }, "ss");
 92 
 93             //执行到这里 你无法确定能否 IsCompleted 啊 ,如果强行endinvoke  不就市区异步的意义了么,
 94             //d1.EndInvoke(iars);
 95 
 96             //比如这里我们等待3秒钟 没有执行完成 就结束线程
 97 
 98             //wait one 就是阻塞主线程 把时间片完全让给 异步委托去执行 ,等待异步委托执行完成 。也是一种失去异步的意义的一种方式
 99             //waitone 的时间 并不代表一定需要执行那么长时间,如果不带时间参数表示等待直至异步线程完成
100             iars.AsyncWaitHandle.WaitOne();
101             Console.WriteLine("wait one 1000");
102             //Thread.Sleep(3000);
103             //if (iars.IsCompleted)
104             //    Console.WriteLine("mydel is complete");
105             //else
106             //{
107             //    Console.WriteLine("mydel is not complete");
108             //}
109             return;//---------------------------------------------------------------------------------------------------
110             //空参数 的lambda 委托写法 去掉action 一样的效果
111             Thread t1 = new Thread(new ThreadStart( new Action(()=>
112             {
113                 MessageBox.Show("t1 process");
114             })));
115             t1.Start();
116             return;//-----------------------------------------------------------------------------------------------------
117             //用lambda的方式来写事件绑定
118             button2.Click += new EventHandler((sender2, e2) =>
119             {
120                 MessageBox.Show("hellow");
121             });
122 
123             //Func 是一个带返回值形式  委托 ,就是微软新搞的一种花样  就是委托
124             //也可用lambda 的方式来写
125             List<string> strArr = new List<string>() {
126                 "xiang",
127                 "zhang",
128                 "chen"        };
129             //var sel = strArr.Where(wheretest);
130             var sel = strArr.Where((r) =>
131             {
132                 if (r.Contains("g"))
133                     return true;
134                 else
135                     return false;
136             });
137 
138             //lamda 方式的action
139             sel.ToList().ForEach(i =>
140             {
141                 Console.WriteLine(i);
142             });
143 
144             return;//-----------------------------------------------------------------------------------------------------
145             List<int> arr = new List<int>();
146             arr.Add(23);
147             arr.Add(45);
148             arr.Add(22);
149             arr.ForEach((i) =>
150            {
151                Console.WriteLine(i + "");
152            });
153         }

 每次看都有不一样的东西,看山不是山 ,人生就是不断的学习。以前以为异步调用就是简单的分一个通道来做事情 ,还真不是那么简单

 1 mydel d;
 2 private void button3_Click(object sender, EventArgs e)
 3 {
 4 
 5     d = new mydel(deldo);
 6     Console.WriteLine("aaa");
 7     //注意下面的d.BeginInvoke(null,null);并不一定要传入asyncCallBack ,根据你情况定 ,
 8     //比如你不需要得到异步调用的结果 (那还不如task.run() ? thread.start()?
 9     //注意 注意 注意 再次说明 这个asynCallBack 在异步方法调用完成后 才会执行 ,仅仅是一个获取结果用 并无特别意思
10 
11     //IAsyncResult ar= d.BeginInvoke(null,null);
12     //deldoend这个方法只有结束时才会调 ,只是相当于结束时候的一个通知 并没有其他意思
13     //如果不这样写 你就无法确定调用何时结束,当然你也可以 在begininvoke 后 同步做一些其他事, 
14     //在最终的时候使用ar.synchandle.waitOne 等待调用结束 ,由此来做到不同线程的同步
15     IAsyncResult ar = d.BeginInvoke(deldoEnd, "hhh");
16     //hhh为你想自定义传入end方法里的参数 end方法里使用ar.asyncState获取
17     Console.WriteLine("bbb");
18 
19     //Thread.Sleep(4000);
20     //Console.WriteLine("rstttt"+d.EndInvoke(ar));
21 
22 }
23 
24 public int deldo()
25 {
26     Console.WriteLine("ccc");
27     Thread.Sleep(3000);
28     Console.WriteLine(555);
29     return 5;
30 }
31 
32 public void deldoEnd(IAsyncResult ar)
33 {
34     Console.WriteLine("ddd");
35     int rest = d.EndInvoke(ar);
36     Console.WriteLine(ar.AsyncState.ToString());
37     Console.WriteLine(rest);
38 }
39 
40 delegate int mydel();

 又是一些新的Task特性的使用方式,还是线程只不过换了种方式:

https://www.cnblogs.com/lonelyxmas/p/9509298.html

https://www.cnblogs.com/jesse2013/p/async-and-await.html

https://www.cnblogs.com/CreateMyself/p/5983208.html

原文地址:https://www.cnblogs.com/assassinx/p/2757601.html