C#中的多线程

Posted Hello Bug.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#中的多线程相关的知识,希望对你有一定的参考价值。

一:线程与进程

对于所有需要等待的操作,例如移动文件,数据库和网络访问都需要一定的时间,此时就可以启动一个新的线程去执行这些耗时的操作,一个进程的多个线程可以同时运行在不同的CPU上或多核CPU的不同内核上。一个进程至少包含一个线程,一个应用程序启动,一般会启动一个进程,然后进程启动多个线程

前台线程与后台线程:只要有任何一个前台进程在运行那么应用程序的进程就会在运行,默认情况下使用Thread创建的线程都是前台线程,使用线程池创建的线程都是后台线程,使用Thread创建的线程可以通过Thread.IsBackground进行设置,当所有前台线程都运行完毕后如果还有后台线程在运行,那么所有的后台线程都会被终止掉


二:线程的开启——通过异步委托

using System;

class MainClass
{
    public static void Main(string[] args)
    {
        Action test1_del = Test1;
        //test1_del.BeginInvoke(null, null);

        Action<int> test2_del = Test2;
        //test2_del.BeginInvoke(11, null, null);

        Func<int> test3_del = Test3;

        //1.通过while循环判断线程是否执行完毕
        //IAsyncResult test3_result = test3_del.BeginInvoke(null, null);
        //while (!test3_result.IsCompleted)
        //{
        //    Console.WriteLine("please wait.....");
        //}
        //Console.WriteLine(test3_del.EndInvoke(test3_result));//得到异步线程的返回值
        //2.通过开启等待句柄的方式设置超时时间,如果大于超时时间还没执行完毕则返回false
        //IAsyncResult test3_result = test3_del.BeginInvoke(null, null);
        //bool isEnd = test3_result.AsyncWaitHandle.WaitOne(1000);
        //3.通过回调函数判断线程是否执行完毕(推荐使用)
        IAsyncResult test3_result = test3_del.BeginInvoke((async) =>
        {
            Console.WriteLine(test3_del.EndInvoke(async));
        }, null);

        Console.WriteLine("this is main");
        Console.ReadKey();
    }

    static void Test1()
    {
        Console.WriteLine("this is test1");
    }

    static void Test2(int a)
    {
        Console.WriteLine("this is test2");
    }

    static int Test3()
    {
        Console.WriteLine("this is test3");
        return 11;
    }
}

二:线程的开启——通过Thread

一个CPU在同一时间只能执行一个线程,当有很多线程需要被执行的时候线程调度器会根据优先级判断先执行哪一个线程,如果优先级相同则逐个执行,可以通过Thread类中的Priority属性去设置优先级

using System;
using System.Threading;

class MainClass
{
    public static void Main(string[] args)
    {
        Thread test1_thread = new Thread(Test1);
        test1_thread.Start();

        Thread test2_thread = new Thread(Test2);
        test2_thread.Start(1);

        //通过Thread类无法开启一个带返回值的线程
        //Thread test3_thread = new Thread(Test3);
        //test3_thread.Start(1);

        Console.WriteLine("this is main");
        Console.ReadKey();
    }

    static void Test1()
    {
        Console.WriteLine("this is test1");
    }

    //使用Thread开启带参数的多线程时参数必须为object类型且参数只能有一个,在开启线程的start方法中传递参数
    static void Test2(object o)
    {
        Console.WriteLine("this is test2");
    }

    static int Test3()
    {
        Console.WriteLine("this is test3");
        return 11;
    }
}

当创建一个线程时,线程的状态是Unstarted状态,当使用Start开启线程后线程的状态仍然是Unstarted状态并不会立即变为Running状态,因为线程调度器会按照顺序选择要执行的线程,当选择到此线程后状态才会被修改为Running状态 


三:线程的开启——通过线程池

一个应用程序只能有一个线程池,线程池是为在某一段时间内创建大量线程设计的,为了提高效率。如果一个线程的时间非常长,就不建议用线程池

using System;
using System.Threading;

class MainClass
{
    public static void Main(string[] args)
    {
        ThreadPool.QueueUserWorkItem(Test1);

        Console.WriteLine("this is main");
        Console.ReadKey();
    }

    static void Test1(object o)
    {
        Console.WriteLine("this is test1");
    }
}

四:线程的开启——通过Task

可以使用Task类中的ContinueWith去设置连续任务,也就是执行完毕一个线程后再去执行下一个线程

using System;
using System.Threading.Tasks;

class MainClass
{
    public static void Main(string[] args)
    {
        //1.使用Start开启线程
        Task test1_task = new Task(Test1);
        test1_task.Start();
        //2.通过TaskFactory开启线程
        TaskFactory test1_taskFactory = new TaskFactory();
        Task task = test1_taskFactory.StartNew(Test1);

        Task test2_task = new Task(Test2, 1);
        test2_task.Start();

        //通过Task类无法开启一个带返回值的线程
        //Task test3_task = new Task(Test3);
        //test3_task.Start();

        Console.WriteLine("this is main");
        Console.ReadKey();
    }

    static void Test1()
    {
        Console.WriteLine("this is test1");
    }

    //使用Task开启带参数的多线程时参数必须为object类型且参数只能有一个,在开启线程的start方法中传递参数
    static void Test2(object o)
    {
        Console.WriteLine("this is test2");
    }

    static int Test3()
    {
        Console.WriteLine("this is test3");
        return 11;
    }
}

五:线程的其他操作

//获取当前线程id
Thread.CurrentThread.ManagedThreadId

//暂停线程
Thread.Sleep(1000);

六:多线程锁

using System;
using System.Threading;

class MainClass
{
    static Object locker = new Object();
    private static int state = 1;
    static void Test()
    {
        while (true)
        {
            lock (locker)//添加互斥锁
            {
                state++;
                if (state == 1)
                {
                    Console.WriteLine("equal 1");
                }
                state = 1;
            }
        }
    }

    static void Main(string[] args)
    {
        Thread t1 = new Thread(Test);
        t1.Start();

        Thread t2 = new Thread(Test);
        t2.Start();
    }
}

以上是关于C#中的多线程的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C# 中的多线程不能达到 100% CPU?

foreach循环中的多线程C#

C#中的多线程启动画面?

python中的多线程和多进程编程

调用本机代码的多线程托管应用程序

C#中的多线程