大话异步与并行(二)

接着上期的文章继续说异步与并行程序员

并行来自于线程的方法实现,异步不必定。这句话,晕倒一大片程序员。编程

首先,多线程序是实现异步一种方法,二者的共同目的:使主线程保持对用户操做的实时响应,如点击、拖拽、输入字符等。使主程序看起来实时都保持着等待用户响应的状态,然后台却有若干件事情在本身干。按消耗资源所在地可分为两类:硬件异步类和CPU异步类。多线程

硬件异步的特色:将须要在后台执行的操做甩给底层硬件去执行,不占用线程和CPU资源。因此说,并非全部的异步都占有线程的。异步

硬件异步类大概有如下这几类。socket

应用程序范围函数

支持包含异步方法的 API测试

Web 访问google

HttpClient ,SyndicationClienturl

处理文件spa

StorageFileStreamWriterStreamReaderXmlReader

使用图像处理

MediaCaptureBitmapEncoderBitmapDecoder

WCF 编程

同步和异步操做

与套接字处理

Socket

 

CPU经常使用的异步方式、方法

一、独立的线程—ThreadStart

     通常状况下,要为不会阻止其余线程的相对较短的任务处理多个线程而且不须要对这些任务执行任何特定调度时,使用 ThreadPool 类是一种最简单的方式。 可是,有多个理由建立您本身的线程:

  • 若是您须要使一个任务具备特定的优先级。

  • 若是您具备可能会长时间运行(并所以阻止其余任务)的任务。

  • 若是您须要将线程放置到单线程单元中(全部 ThreadPool 线程均处于多线程单元中)。

  • 若是您须要与该线程关联的稳定标识。 例如,您应使用一个专用线程来停止该线程,将其挂起或按名称发现它。

  • 若是您须要运行与用户界面交互的后台线程,.NET Framework 2.0 版提供了 BackgroundWorker 组件,该组件可使用事件与用户界面线程的跨线程封送进行通讯。

二、ThreadPool—ThreadPool.QueueUserWorkItem(M())

三、任务,Task系列--普通任务、关联的任务(Task<T>.ContinueWith(…))、父子任务、任务工厂(TaskTactory<TResult>)

四、Parallel静态类--- System.Threading.Tasks.Parallel.For(…) System.Threading.Tasks.Parallel.ForEach(…) Parallel.Invoke(() => Sort());

五、PLINQ

六、定时器  

到此只是简单的基础知识阐述。若是不太清楚,下面的陆续的文章将会一一讲起。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Thread类(线程类)

除了使用委托建立线程以外,还可使用thread 类建立线程

        static void Main(string[] args)
        {
            Thread t = new Thread(ThreadMain);
            t.Start();
            Console.WriteLine("This ia a mian thread.");
        }

        static void ThreadMain()
        {
            Console.WriteLine("Running in a thread.");
        }

简化以上代码 

 static void Main(string[] args)
        {
            new Thread(() =>
            Console.WriteLine("Running in a thread.")

        ).Start();
          
            Console.WriteLine("This ia a mian thread.");
        }

再次见证  拉姆达(lambda)表达式与匿名方法 的威力。

在上面简单的Thread类就建立并开始了一个线程。Thread类默认的是 IsBackground =false,也就是说它是前台线程。

说到前台线程与后台线程,上一文章提到,当前台进程中止的时候,后台进程也将中止,当时是放在mian主线程测试的,必须关闭或结束主线程,看的不是太清楚

如今有了Thread类,下面的例子将会开启不依懒主线程的测试。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            DateTime now = DateTime.Now;

            Thread t1 = new Thread(() =>
            {
                Console.WriteLine("Running in a thread t1.");
                Func<decimal, int, decimal> f = (money, ms) =>
                {
                    Console.WriteLine("SaveBankAccountPersonA thread started! current run at threadID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine("SaveBankAccountPersonA thread IsBackground " + Thread.CurrentThread.IsBackground);
                    Thread.Sleep(ms);
                    Console.WriteLine("SaveBankAccountPersonA thread completed!");
                    return ++money;
                };

                var ar = f.BeginInvoke(1, 200, (r) =>
                {
                    if (r == null)
                    {
                        throw new ArgumentNullException("r");
                    }

                    Thread.Sleep(1000);

                    Console.WriteLine("AsycyCallBackCurrentMoneyPersonA:{0}", f.EndInvoke(r));
                    Console.WriteLine("AsycyCallBackRunTimePersonA:{0}", (DateTime.Now - now).TotalSeconds);
                    Console.WriteLine("AsycyCallBackSaveBankAccountPersonA thread IsBackground " + Thread.CurrentThread.IsBackground);

                }, null);

                while (!ar.IsCompleted)
                {
                    Console.WriteLine("threadT1 wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(50);
                }
            });

            Thread t2 = new Thread(() =>
            {

                Console.WriteLine("Running in a thread t2.");
                Func<decimal, int, decimal> f = (money, ms) =>
                {
                    Console.WriteLine("SaveBankAccountPersonB thread started! current run at threadID:" + Thread.CurrentThread.ManagedThreadId);
                    Console.WriteLine("SaveBankAccountPersonB thread IsBackground " + Thread.CurrentThread.IsBackground);
                    Thread.Sleep(ms);
                    Console.WriteLine("SaveBankAccountPersonB thread completed!");
                    return ++money;
                };

                var ar = f.BeginInvoke(1, 200, (r) =>
                {
                    if (r == null)
                    {
                        throw new ArgumentNullException("r");
                    }
                    Console.WriteLine("AsycyCallBackCurrentMoneyPersonB:{0}", f.EndInvoke(r));
                    Console.WriteLine("AsycyCallBackRunTimePersonB:{0}", (DateTime.Now - now).TotalSeconds);
                    Console.WriteLine("AsycyCallBackSaveBankAccountPersonB thread IsBackground " + Thread.CurrentThread.IsBackground);

                }, null);

                while (!ar.IsCompleted)
                {
                    Console.WriteLine("threadT2 wating current run at treadID:" + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(50);
                }
            });

            t1.Start();
            t2.Start();
            t1.Abort();

            Console.WriteLine("This ia a mian thread.");
            Console.ReadKey();
        }
    }
}

上面的代码不少,对上一文章的进行扩展。分别启用两个线程t1和t2 ,并在每一个线程里加入异步委托A和B,从而开始新的后台线程(异步委托默认是后台线程)

上面这张图,t1尚未来及运行,就已中止,下面这张图,t1运行起来了

可是A仍是没有运行起来,充分说明A一并被t1中止

 

后台线程A和B 同时拥有两个回调函数 ,在A回调函数里 加入了Sleep(1000) 延迟1秒,紧接着外面t1.Abort();结束前台线程t1。从而达到,外面的t1前台线程结束时后台线程A尚未来及结束(实际上已强制性并随t1前台线程结束了!)

这样就验证了,前台线程结束所依懒的后台线程所并随结束的事实!代码就是最好的说明

 

小结:本节在文章一节中着重阐述的前台线程与后台线程做了在Thread类基础上作了实例论证,从而证实,后台线程的生命周期由依懒的前台线程结束而结束。

同时也将异步与多线程进一步举例说明,线程只是异步的一种实现方法!

 

 未完待续...

相关文章
相关标签/搜索