首页 > 编程语言 > 详细

C#线程处理

时间:2019-02-19 00:09:26      阅读:175      评论:0      收藏:0      [点我收藏+]

??C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
??除非被指定,否则所有的例子都假定以下命名空间被引用了:

using System;
using System.Threading;

C#开启线程的方法有:

  • 异步委托
  • 通过Thread类
  • 线程池
  • 任务

??总的来说其实线程的开启基本都涉及到委托的使用。

一、异步委托开启线程

首先来看一个比较简单的例子,采用第一种开启线程的方法——异步委托

using System;
using System.Threading;

namespace Study
{
    class Program
    {
        static void test()
        {
            Console.WriteLine("TestThread");
        }
        static void Main(string[] args)
        {
            Action a = test;
            a.BeginInvoke(null, null);
            Console.WriteLine("MainThread");
            Console.ReadLine();
        }
    }
}

??编译运行,发现结果与预期有所不同。结果如下图
技术分享图片
??如果按着逐行运行代码的方式,那么应该是先输出TestThread,但是结果却是先输出MainThread。
??将a.BeginInvoke(null,null);Console.WriteLine("MainThread");对调位置之后,结果和之前的依然一致。这就说明,异步委托开启的线程是和主线程同时同步进行的。
??Action委托是指向一个没有返回值的函数,那么假设一个线程,我们需要取得他的返回结果并输出,那么就要用到Func委托。
??看下面的源码

using System;
using System.Threading;

namespace SummerStudy
{
    class Program
    {
        static string test(int i, string str)
        {
            Console.WriteLine("TestThread" + "\t参数i是:" + i);
            return str;
        }
        static void Main(string[] args)
        {
            Func<int, string, string> a = test;
            IAsyncResult res = a.BeginInvoke(1, "返回值", null, null);
            string o = a.EndInvoke(res);
            Console.WriteLine("MainThread\t" + "线程返回值是:" + o);
            Console.ReadLine();
        }
}

技术分享图片
同时异步委托开启线程中,判断线程是否结束的方法也有两种,一种是利用IAsyncResult的IsCompleted方法,一种是使用方法进行线程结束判断。
??具体使用方法如下。

  1. IsCompleted(bool)
IAsyncResult ia = a.BeginInvoke()
if(ia.IsCompleted == false)
{
    //GoOn
}
  1. AsyncWaitHandle
IAsyncResult ia = a.BeginInvoke()
ia.AsyncWaitHandle.WaitOne(Time);//Time为等待时间,超时后才会运行下一行代码,未完成直接跳出返回false

??或者通过自定义方法,BeginInvoke中倒数第二个参数是一个委托,传递一个函数,在线程结束之后会自动的调用。

static string Test(int a)
{

}
Func<int, string> a = Test;
IAsyncResult ia = a.BeginInvoke(100, CallBack, a);
static void CallBack(IAsyncResult ar)
{
    Func<int, string> a = ia.AsyncState as Func<int, string>;
    string res = a.EndInvoke(ar);
}

??在使用Lambda表达式作为委托的时候,最后一个参数可以为空,因为Lambda表达式可以访问外部变量。

二、使用Thread类开启线程

??使用Thread类创建一个实例,它的构造方法中需要传递一个委托。通过委托绑定线程。
??直接上代码

using System;
using System.Threading;

namespace Study
{
    class Program
    {
        static void test()
        {
            Console.WriteLine("Thread");
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");
        }
        static void Main(string[] args)
        {
            Thread t = new Thread(test);
            t.Start();
            Console.WriteLine("Main");
            Console.Read();
        }
    }
}

技术分享图片
??对于需要传递参数的委托,则必须制定参数类型为object,在线程Start方法中传递参数

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t线程id为" + id + ",\t参数是:" + c);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            Thread t = new Thread(test);
            t.Start("xxx.avi");
            Console.WriteLine("Main");
            Console.Read();
        }
    }
}

技术分享图片
??当然你也可以自定义一个类,在类中自定义数据传递。

三、线程池

??这种方法有助于节省时间,具体使用方法如下

using System;
using System.Threading;

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t线程id为" + id + ",\t参数是:" + c);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(test, "asfasf");
            Console.Read();
        }
    }
}

??其中委托必须要有一个参数,无论是否使用该参数。且只适用于使用时间短的线程,不能改变优先级

四、任务

??使用Task类开启线程,还有TaskFactory创建
??Task类实例

using System;
using System.Threading;
using System.Threading.Tasks;

namespace SummerStudy
{
    class Program
    {
        static void test(object c)
        {
            int id = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine("Thread,\t线程id为" + id);
            Thread.Sleep(2000);
            Console.WriteLine("TimeOver");

        }
        static void Main(string[] args)
        {
            Task t = new Task(test, "Asfgasg");
            t.Start();

            //或者

            TaskFactory tf = new TaskFactory();

            Task t1 = tf.StartNew(test);
            Console.Read();
        }
    }
}

我的掘金:WarrenRyan

我的简书:WarrenRyan

欢迎关注我的博客获得第一时间更新 https://blog.tity.xyz

我的Github:WarrenRyan

我的博客园:WarrenRyan

C#线程处理

原文:https://www.cnblogs.com/WarrenRyan/p/10398669.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!