zoukankan      html  css  js  c++  java
  • c#使用多线程的几种方式示例详解

    (1)不需要传递参数,也不需要返回参数

    ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值。

    class Program
    {
    static void Main(string[] args)
    {
    for (int i = 0; i < 30; i++)
    {
    ThreadStart threadStart = new ThreadStart(Calculate);
    Thread thread = new Thread(threadStart);
    thread.Start();
    }
    Thread.Sleep(2000);
    Console.Read();
    }
    public static void Calculate()
    {
    DateTime time = DateTime.Now;//得到当前时间
    Random ra = new Random();//随机数对象
    Thread.Sleep(ra.Next(10,100));//随机休眠一段时间
    Console.WriteLine(time.Minute + ":" + time.Millisecond);
    }
    }

    (2)需要传递单个参数

    ParameterThreadStart委托定义为void ParameterizedThreadStart(object state),有一个参数但是没有返回值。

    class Program
    {
    static void Main(string[] args)
    {
    for (int i = 0; i < 30; i++)
    {
    ParameterizedThreadStart tStart = new ParameterizedThreadStart(Calculate);
    Thread thread = new Thread(tStart);
    thread.Start(i*10+10);//传递参数
    }
    Thread.Sleep(2000);
    Console.Read();
    }
    public static void Calculate(object arg)
    {
    Random ra = new Random();//随机数对象
    Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
    Console.WriteLine(arg);
    }
    }

    (3)使用专门的线程类(常用)

    使用线程类可以有多个参数与多个返回值,十分灵活!

    class Program
    {
    static void Main(string[] args)
    {
    MyThread mt = new MyThread(100);
    ThreadStart threadStart = new ThreadStart(mt.Calculate);
    Thread thread = new Thread(threadStart);
    thread.Start();
       //等待线程结束
    while (thread.ThreadState != ThreadState.Stopped)
    {
    Thread.Sleep(10);
    }
    Console.WriteLine(mt.Result);//打印返回值
    Console.Read();
    }
    }
    public class MyThread//线程类
    {
    public int Parame { set; get; }//参数
    public int Result { set; get; }//返回值
    //构造函数
    public MyThread(int parame)
    {
    this.Parame = parame;
    }
    //线程执行方法
    public void Calculate()
    {
    Random ra = new Random();//随机数对象
    Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
    Console.WriteLine(this.Parame);
    this.Result = this.Parame * ra.Next(10, 100);
    }
    }

    (4)使用匿名方法(常用)

    使用匿名方法启动线程可以有多个参数和返回值,而且使用非常方便!

    class Program
    {
    static void Main(string[] args)
    {
    int Parame = 100;//当做参数
    int Result = 0;//当做返回值
    //匿名方法
    ThreadStart threadStart = new ThreadStart(delegate()
    {
    Random ra = new Random();//随机数对象
    Thread.Sleep(ra.Next(10, 100));//随机休眠一段时间
    Console.WriteLine(Parame);//输出参数
    Result = Parame * ra.Next(10, 100);//计算返回值
    });
    Thread thread = new Thread(threadStart);
    thread.Start();//多线程启动匿名方法
    //等待线程结束
    while (thread.ThreadState != ThreadState.Stopped)
    {
    Thread.Sleep(10);
    }
    Console.WriteLine(Result);//打印返回值
    Console.Read();
    }
    }

    (5)使用委托开启多线程(多线程深入)

    1、用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程

    BeginInvoke方法可以使用线程异步地执行委托所指向的方法。然后通过EndInvoke方法获得方法的返回值(EndInvoke方法的返回值就是被调用方法的返回值),或是确定方法已经被成功调用。

    class Program
    {
    private delegate int NewTaskDelegate(int ms);
    private static int newTask(int ms)
    {
    Console.WriteLine("任务开始");
    Thread.Sleep(ms);
    Random random = new Random();
    int n = random.Next(10000);
    Console.WriteLine("任务完成");
    return n;
    }
    static void Main(string[] args)
    {
    NewTaskDelegate task = newTask;
    IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
    //EndInvoke方法将被阻塞2秒
    int result = task.EndInvoke(asyncResult);
    Console.WriteLine(result);
    Console.Read();
    }
    }

    2、使用IAsyncResult.IsCompleted属性来判断异步调用是否完成

    class Program
    {
    private delegate int NewTaskDelegate(int ms);
    private static int newTask(int ms)
    {
    Console.WriteLine("任务开始");
    Thread.Sleep(ms);
    Random random = new Random();
    int n = random.Next(10000);
    Console.WriteLine("任务完成");
    return n;
    }
    static void Main(string[] args)
    {
    NewTaskDelegate task = newTask;
    IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
    //等待异步执行完成
    while (!asyncResult.IsCompleted)
    {
    Console.Write("*");
    Thread.Sleep(100);
    }
    // 由于异步调用已经完成,因此, EndInvoke会立刻返回结果
    int result = task.EndInvoke(asyncResult);
    Console.WriteLine(result);
    Console.Read();
    }
    }

    3、使用WaitOne方法等待异步方法执行完成

    WaitOne的第一个参数表示要等待的毫秒数,在指定时间之内,WaitOne方法将一直等待,直到异步调用完成,并发出通知,WaitOne方法才返回true。当等待指定时间之后,异步调用仍未完成,WaitOne方法返回false,如果指定时间为0,表示不等待,如果为-1,表示永远等待,直到异步调用完成。

    class Program
    {
    private delegate int NewTaskDelegate(int ms);
    private static int newTask(int ms)
    {
    Console.WriteLine("任务开始");
    Thread.Sleep(ms);
    Random random = new Random();
    int n = random.Next(10000);
    Console.WriteLine("任务完成");
    return n;
    }
    static void Main(string[] args)
    {
    NewTaskDelegate task = newTask;
    IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
    //等待异步执行完成
    while (!asyncResult.AsyncWaitHandle.WaitOne(100, false))
    {
    Console.Write("*");
    }
    int result = task.EndInvoke(asyncResult);
    Console.WriteLine(result);
    Console.Read();
    }
    }

    4、使用回调方式返回结果

    要注意的是“my.BeginInvoke(3,300, MethodCompleted, my)”,BeginInvoke方法的参数传递方式:

    前面一部分(3,300)是其委托本身的参数。

    倒数第二个参数(MethodCompleted)是回调方法委托类型,他是回调方法的委托,此委托没有返回值,有一个IAsyncResult类型的参数,当method方法执行完后,系统会自动调用MethodCompleted方法。

    最后一个参数(my)需要向MethodCompleted方法中传递一些值,一般可以传递被调用方法的委托,这个值可以使用IAsyncResult.AsyncState属性获得。

    class Program
    {
    private delegate int MyMethod(int second, int millisecond);
    //线程执行方法
    private static int method(int second, int millisecond)
    {
    Console.WriteLine("线程休眠" + (second * 1000 + millisecond) + "毫秒");
    Thread.Sleep(second * 1000 + millisecond);
    Random random = new Random();
    return random.Next(10000);
    }
    //回调方法
    private static void MethodCompleted(IAsyncResult asyncResult)
    {
    if (asyncResult == null || asyncResult.AsyncState == null)
    {
    Console.WriteLine("回调失败!!!");
    return;
    }
    int result = (asyncResult.AsyncState as MyMethod).EndInvoke(asyncResult);
    Console.WriteLine("任务完成,结果:" + result);
    }
    static void Main(string[] args)
    {
    MyMethod my = method;
    IAsyncResult asyncResult = my.BeginInvoke(3,300, MethodCompleted, my);
    Console.WriteLine("任务开始");
    Console.Read();
    }
    }

    5、其他组件的BeginXXX和EndXXX方法

    在其他的.net组件中也有类似BeginInvoke和EndInvoke的方法,如System.Net.HttpWebRequest类的BeginGetResponse和EndGetResponse方法。其使用方法类似于委托类型的BeginInvoke和EndInvoke方法,例如:

    class Program
    {
    //回调函数
    private static void requestCompleted(IAsyncResult asyncResult)
    {
    if (asyncResult == null || asyncResult.AsyncState==null)
    {
    Console.WriteLine("回调失败");
    return;
    }
    HttpWebRequest hwr = asyncResult.AsyncState as HttpWebRequest;
    HttpWebResponse response = (HttpWebResponse)hwr.EndGetResponse(asyncResult);
    StreamReader sr = new StreamReader(response.GetResponseStream());
    string str = sr.ReadToEnd();
    Console.WriteLine("返回流长度:"+str.Length);
    }
    static void Main(string[] args)
    {
    HttpWebRequest request =
    (HttpWebRequest)WebRequest.Create("http://www.baidu.com");
    //异步请求
    IAsyncResult asyncResult = request.BeginGetResponse(requestCompleted, request);
    Console.WriteLine("任务开始");
    Console.Read();
    }
    }
  • 相关阅读:
    HDU2059(龟兔赛跑)
    pat 1012 The Best Rank
    pat 1010 Radix
    pat 1007 Maximum Subsequence Sum
    pat 1005 Sign In and Sign Out
    pat 1005 Spell It Right
    pat 1004 Counting Leaves
    1003 Emergency
    第7章 输入/输出系统
    第六章 总线
  • 原文地址:https://www.cnblogs.com/vaevvaev/p/7127600.html
Copyright © 2011-2022 走看看