线程和异步

Posted cdjbolg

tags:

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

线程与进程

进程和线程放在一起谈比较好理解。

进程可理解为一个应用程序。一个进程中只有一个任务,就是单线程,有多个任务就是多线程。

下面附上一个线程的小例子。

技术图片
 public class Printer
    {
        public void PrintNumbers()
        {
            Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name);

            Console.Write("Your numbers: ");
            for (int i = 0; i < 5; i++)
            {

                Console.Write("{0}", i);
                Thread.Sleep(2000);//间隔2秒
            }

        }

    }
class Program
    {
        static void Main(string[] args)
        {
            Printer print = new Printer();
            ThreadStart thread = print.PrintNumbers;//ThreadStart委托
            Thread t = new Thread(thread);
            t.IsBackground = true;//默认为前台线程,不会随Main()方法的结束而结束。可以设置thread.IsBackground为True,则转为后台线程,即可随Main()方法的结束而结束。
            t.Start();
            //Thread t = new Thread(new ThreadStart(print.PrintNumbers));
            //t.Name = "Thread";
            //t.Priority = ThreadPriority.Highest;
            //t.Start();
//第一种写的清楚点,第二种写的简易。
            MessageBox.Show("************test************");
        }
}
View Code

开启一个线程运行Print操作 同时也显示了提示信息。如果不用线程则将等Print结束后才可以显示提示信息。

前后台线程在进行解释:前台线程可以阻止应用程序的终结,要一直等到所有前台线程结束方可终结,而后台线程当应用程序终结时,所有的后台线程也自动终止。

创建10个线程

 

Thread [] threads= new Thread[10];
for(int i=0;i<10;i++)
{
threads[i]=new Thread(new ThreadStart(XX方法名));
}

 

并发问题

多线程共同使用某个共享资源的时候,会造成冲突。

举个生活例子以及解救方法

 

生活中我们会遇到这样的情况:去商场买衣服时,如果想要试一试是否合身,一般可以利用商场提供的试衣间,但一个试衣间一个时间段内只能有一个人在试衣。如果有多个人都要使用同一个试衣间(共享资源),而试衣间的门又没有加锁,则会存在共享资源的冲突问题。
实际生活中,这个问题是这样解决的:
现在假设有A、B、C同时要使用试衣间,A进去后,将门锁上,B看到门已上锁,则知道有人在试衣,会进行等待,A使用完试衣间后,打开锁(解除对共享资源的锁定),则B知道此时试衣间可以使用,则B使用试衣间。C同样。
简单的一把锁,解决了试衣间的使用冲突问题。

 

在代码中使用lock关键字来进行锁定。

 

技术图片
public class Printer
    {
        private object threadLock = new object();

        public void PrintNumbers()
        {
            lock (threadLock)//所有的代码都必须在锁定范围中
            {
                Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name);

                Console.Write("Your numbers: ");
                for (int i = 0; i < 5; i++)
                {
                    Console.Write("{0}", i);
                    Thread.Sleep(2000);
                }
            }
        }
 
    }
View Code

 

线程池 

同样使用Print操作来展示线程池的例子。

技术图片
public class Printer
    {
        private object threadLock = new object();

        public void PrintNumbers()
        {
            lock (threadLock)
            {
                Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name);

                Console.Write("Your numbers: ");
                for (int i = 0; i < 5; i++)
                {
                    Console.Write("{0}", i);
                    Thread.Sleep(2000);
                }
            }
        }
    }

 class Program
    {


        public static void PrintTheNumbers(object state)
        {
            Printer task = (Printer)state;//传入对象转化成自定义类并调用方法传入委托WaitCallback
            task.PrintNumbers();
        }

        static void Main(string[] args)
        {
            Printer p = new Printer();
            WaitCallback workItem = new WaitCallback(PrintTheNumbers);//WaitCallBack是委托 通过New也可以启用多个线程
            ThreadPool.QueueUserWorkItem(workItem, p);//启动线程池
            Console.ReadLine();
        }
    }
View Code

线程池好处:

1. 线程池减少了线程的创建,开始和停止的次数,提高了效率;

2.使用线程池,可以将注意力放到业务逻辑上而不是多线程架构上。

 与线程作用异曲同工之妙的是异步调用。

异步与多线程解决的是多并发问题(类似买票会争抢资源)。

异步不需要等待返回值就继续执行,同步需要等待返回值。

返回值的意思是否将数据成功写到底层缓冲。写入成功返回True,否则为false;

阻塞和非阻塞的区别在于没有数据到达的时候是否立刻返回。阻塞会等到写完数据最后返回,非阻塞能写多少写多少。

同样也给一个例子。

技术图片
public delegate void BinaryOp();

    public class Printer
    {
        private object threadLock = new object();

        public void PrintNumbers()
        {
            lock (threadLock)
            {
                Console.WriteLine("->{0} is executing PrintNumbers()", Thread.CurrentThread.Name);

                Console.Write("Your numbers: ");
                for (int i = 0; i < 5; i++)
                {
                    Console.Write("{0}", i);
                    Thread.Sleep(2000);
                }
            }
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            Printer a = new Printer();
            BinaryOp b = a.PrintNumbers;//该方法无参 故下面两个NULL
            IAsyncResult result = b.BeginInvoke(null, null);//开启异步调用
            MessageBox.Show("************test************");
            Console.ReadLine();
        }
    }
View Code

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

第十次总结 线程的异步和同步

线程池与并行度

进程线程同步异步

异步代码、共享变量、线程池线程和线程安全

多线程更新UI的常用方法

8异步和多线程