Advanced_C#_Skill_Task Parallel Library_vs_Lambda Expressions_任務和線程差在哪裡?線程池又是捨麼??



在我們了解Task之前

對於多線程,我們經常使用的是Thread

如果我們要使用多核的功能可能就會自己來開線程,

然而這種線程模型在.net 4.0之後被一種稱為基於「任務的編程模型」所沖擊,

原因在於  task會比thread所需消耗的性能來的更小

不過大家肯定會有疑惑,任務和線程到底有什麽區別呢?






Threads(線程/執行緒)

Threads are real OS thread with own its stack and resources. Threads allow to developer be fully controlled (by using Resume(), Suspend() or Abort() and etc). The problem is that threads are "time hungry" entities, which means that they will consume non trivial time at creation stage. In additional we should take in consideration time for context switching overhead performed by CPU.


Task(任務)

Task is class introduces as part of TPL [Task Paralel Library] and it came with CLR 4.0.  Task represent compromise of above cases. It relays on TaskScheduler which in his turn working against ThreadPool.

Task able to return result after it completes (unlike ThreadPool). In addition we can run another task immediately when first one is completes.



Task and Thread

Let us first understand the relationship between task and thread.  See the following figure.


Typically task is resided(存在于) in a thread.
A task may contain one or more child tasks those are not necessarly resided in the parent task’s thread.  In the above figure, Child Task M2 of Task M resided in Thread B.


 Task(任務)  和  Thread(線程/執行緒) 的區別:

1、Task是架構在Thread之上的,也就是說Task最終還是要拋給Thread去執行。


2、 Task(任務)Thread(線程/執行緒)不是一對一的關系,

比如開10個任務並不是說會開10個線程,

這一點任務有點類似線程池(ThreadPool)

但是任務相比線程池有很小的開銷和精確的控制。


ThreadPool

ThreadPool is entity that optimize overheads of the threads and it manage them [threads] by itself. In return it gives developer small maneuver possibilities such as pool size and ability to submit work to execute at some point. And thats it!





在多線程編程中,線程的創建和銷毀是非常消耗系統資源的,
因此,C#引入了池的概念,維護一個池,
池內維護的一些線程,需要的時候從池中取出來,
不需要的時候放回去,這樣就避免了重複創建和銷毀線程。



自己一開始對這個名詞的解釋及感覺

線程池  給我的感覺很像一個魚塭或者一個養魚的魚池
一個大池塘裏頭存放了很多給我們吃的魚
我們一個人就好比為一種應用程式
我們都知道應用程式在運行時會消耗資源
這裡我就比喻為工作上班或者讀書讀到很晚
你餓了累了需要吃一點池子裡的魚你才能繼續工作讀書奮鬥
你有需要再去取魚 這就是一個 ThreadPool的比較生活化的比擬
池子中一條條的魚就好比為一條條的 Thread 線程
用來供應我們蛋白質或者豐富的DHA 而這些在電腦世界中我們稱之為資源(Resource)













可是這個比喻並不好因為魚被吃掉就消化掉了
並不能重複利用
並不能再丟到池子裏頭
















前陣子在台北有做過Uber
覺得Uber是個可以解釋的例子
假設我說台北區域包含了一堆Uber的汽車
台北居民人手一支手機,手機當中有叫Uber的App
那我就說充斥著Uber的台北這塊區域是一個"Uber的池子"
當我需要我就叫Uber不需要Uber就回去池子中洄游
這個比擬感覺比較OK  雖然可能跟一般教科書或者程式課本、論壇上
比較死版、八股的定義上比起來會有些許差異
但是大概80%是可以被接受的





Thread Pooling

Thread pooling is the process of creating a collection of threads during the initialization of a multithreaded application, and then reusing those threads for new tasks as and when required, instead of creating new threads.

Then every process has some fixed number of threads depending on the amount of memory available, those threads are the need of the application but we have freedom to increase the number of threads.

(1).Every thread in the pool has a specific given task.

(2).The thread returns to the pool and waits for the next assignment 
when the given task is completed.

Usually, the thread pool is required when we have number of threads are created to perform a number of tasks, in this organized in a queue. Typically, we have more tasks than threads.

As soon as a thread completes its task, it will request the next task from the queue until all tasks have been completed. The thread can then terminate, or sleep until there are new tasks available.











One of the typically more complicated topics to understand within any sort of language

but in your development career that you're going to run into probably
                                                                                                     (很可能;大概)
and that has to do with parallel or asynchronous programming which really just at
                                                         (異步的)
the end of the day means I want to be able to execute multiple instructions on a CPU or

on multiple core CPUs  at the same time.


In previous versions of dot Net and C sharp

we were forced to do this through the system that threading namespace

and while this was able to get the job done it required us to write a lot of

overhead code in order to create these threads spawn them off  have them execute some
                                                            spawn 閃靈悍將 、 大量產生--->翻譯有待修改
sort of operations checck when they're done pass into them some sort of delegates or something
(一半一半,說話沒有十足把握時用 sort of 或 kind of 來緩和語氣)
of that nature to execute when they were done or function pointers to execute

when they were done and so there was a lot of overhead there that we were really required

to do in order to just really get things going and then heaven forbid you had to do any sort

of synchronization and making sure that you're letting go of resources

when you're supposed to not having any deadlocks and things of that nature really

got to be quite a mess and really a headache to maintain and really a lot of people

shied away from it because of that
(因不喜歡、害怕或缺乏自信而)退縮,躲避,畏避
also one of the bigger problems with using raw treads in that way is

that it is possible if you are running on an older machine and you simply had a single

single core processor and you try to spin up a bunch of extra threads
(單核心處理器)                            (加快運轉)  (一束、一串)
to try to run several operations at the same time you could really overloaded
                                                      (同時地)                                     (超載)
actually to the detriment of your application cause a lot of context switching
                     (不利、損失)                                                    (內文切換)

當CPU從一個process切到另一個process執行之前,OS必須保存原有process的執行狀態,
同時載入New Process的執行狀態
Context switching是一系統負擔,其時間長短,幾乎完全取決於Hardware因素
利用Thread(light-weighted process)來取代process

得以降低context switching負擔

on the CPU between those threads because it was trying to execute them

as parallel as possible but since there was only one core could only execute one

instruction at a time and had to switch between them so that is very
(指示,命令)
costly to your CPU , is very costly to your system and actually why is that

typically slowing down your performance .
                                                   (效能)

Microsoft took a lot of these things back to the drawing board

and said how can we improve this how can we give our developers

the opportunity to continue to write asynchronous code or code that can be run

in parallel but get rid of a lot of headache and make it more intuitive to how they were
                          (擺脫)                                                         (憑直覺獲知的、直覺的)
typically write code today





In this lesson , I'm going to take you through the Task Parallel Library

or TPL and show you how tasks are able to alleviate a lot of stress and a lot of the
                                                                    (減輕,使緩和)    (壓力)
problem with writing parallel code and allow you to do it quite easily.

=============================================================



New a console application at first!!!



Now I do have to do a little bit of setup here as you know in the previous lessons

I turn to write some code and then I'll hit the Ctrl+F5 and that really

runs the application in debug mode so that there is a line at the end of the console

application waiting for you to hit any key at that point it's kind of blocked all of the executions

of any other tthreads or anything going on in the background and we're not able to see anything

else execute so in order for me to properly show you some of these techniques

and I want to show you we're going to have to shy away from the debugging aspect

and using Ctrl+F5 and just write our own sort  of stopper at the end of the application

so we can stop the console application from finishing but still allow

us to see some code being executed on other threads other tasks

in order to do that I'm simply going to drop down a few lines here and I'm going to a

Console.WriteLine and right in here a press any key to quit so

this is really going to serve the same purpose as the Ctrl+ F5

and After someone going to say Console ReadKey which going to sit here and

wait for keyboard input from the user and it will sit  here not blocking waiting for me to

press anything on the keyboard so if I hit F5  at this point

you're going to see press any key to quit

it will sit here indefinitely I can hit any can hear hit

this is going to allow me o write a little bit more code

so you can see things execute as we go

======================================================================

So what does the TPL of the Task Parallel Library do for us

that threading couldn't do or are how do we actually use these tasks

in this library for us well it's quite simple actually so the first thing I want to do

is I want to create a task

I want to call this t1 and  I want to say this is equal to a new task




If you see here there's

a number of overloads but the most common one at least for this course is

going to be the action and if you recall from our lessons on delegates anonymous method

and lambda expressions this is merely a generic delegate and since there is

no generic parameterize type on this action that means there are no inputs to this

在 C# 2.0 以前的版本中,宣告委派 (Delegate) 的唯一方式是使用具名方法。  C# 2.0 引進了匿名方法 (Anonymous Method),在 C# 3.0 (含) 以後版本,則以 Lambda 運算式取代匿名方法來做為撰寫內嵌 (Inline) 程式碼的慣用方式。

Lambda 運算式  Syntatic sugar

分三部分

Left-hand side
(1).Parameter(s)  that can be 0 , 1 or more parameters ....

Center
(2). =>  "equals greater than" sign          means    "goes to" operator is also called the lambda operator

Right-hand side                                                                                
(3).Expression or a series of Statements

Expression Lambda
Left-hand side    Center      Right-hand side 
( Person person )      =>     person.FirstName == "Sam"

Statement Lambda

(object sender , EventArgs args) =>
{
        ListBox.ItemSource = args.Resullt;
        Console.WriteLine("Hello");
}

When we talking about an expression lambda this is going to return some

type of value so in our example here we see we have a variable that's called

person and also of type person and then we have the cool and operator

in the middle and then we're taking the first name property of our parameter

and comparing it to the string "Sam" and this is obviously going to return a true or false

this is a shorthand version of writting out public school some method  as a parameter

and then returning the result of the evalution of first name is equal to "Sam"


If we want to assign a method signature to this particular lambda expression

the method would be a method that takes one parameter of type person and returns a boolean

so it return a true / false value so that would be a signature that this lambda would match up to

are all expression lambdas predicates meaning they're all returning true/ false



參考自:
https://msdn.microsoft.com/zh-tw/library/0yw3tz5k.aspx

Getting Started with Lambda Expressions with Jeremy Clark

https://www.youtube.com/watch?v=xev-kNmz_a0




so let's go ahead and check that out so what we can do is we can create

a lambda expressions which is  more comfortable with and since we don't have any

inputs that means open and closed paarenthesis with anothing in it

we have our lambda operator here the equals and more than symbol

and then we need to do something here



what is the task we want to complete well we could do a number of different things

but i'm simply going to create a very simple lambda expression


here and i'm going to say here that

Console.WriteLine task one is beginning and

then I will do some sort of Thread.sleep just to kind of pretend



that there's something else going on here in the background thread that sleep

if your underwears in the system dot threading namespace

in it is laeft over from much earlier versions of dot Net framework

but now it's really quite simple just takes in a number of milliseconds that

you want it to sit here and wait I'm gonna give it a thousand which basically

means I want you to sit here for a second and then I'm going to another

Console.WriteLine it's going to say task 1 has completed

So now we've created our task and we've given it an action what we wanted to perform and

so now let's see what happens Ctrl+F5



起始非同步工作

TPL 的核心類別是 Task


when you create a task in this way

Now there are other ways to create and I'll show you that in a few moments

but you create them in this way they don't start automatically.

you have to  explicitly tell them to start using task.Start() instance method
要記得  Start 才會開始工作
語法:  task.Start();   // 起始工作。

so now if we hit save and hit F5 you're going to see press any key to quit but also that

task one is beginning and task was completed so that was fairly quick

it was only a second in between I mean but if you  see I had to sleep for 2 seconds

and hit F5 will see there a little bit longer task one is beginning

task one has completed




第一階段 練習code


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

namespace Task_Parallel_Library
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Task(() =>{
                Console.WriteLine("task 1 is beginning");
                Thread.Sleep(1000); 1 second
                Console.WriteLine("task 1 is has completed");
            });
            t1.Start();
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }
    }
}
//


Okay well it's not overly interesting

I'm not actually having this application do anything else while these tasks are executing

but where the task parallel library and tasks really start to shine is when you want to do

multiple things multiple operations or even multiple tasks at the same time.





So what I'm going to do now is I'm going to refactor this a little bit

because I want to share this code between multiple tasks


but I don't want just copy and paste this because

as you know from my previous lessons I can't stand duplication of my code

so what I'm going to do here is I'm going to create a new method

a static void method that's called  "Do some very  impportant work"

and I'm going to pass in a couple arguments

I'm going to pass in an it's going to an ID and I'm also going to pass in

and another end that's going to be sleep time so I can configure

this across multiple threads or multiple tasks

so I'm going to cut this logic out of here I'll paste in here and

I'm going to do a little bit of formatting in here nothing you haven't seen before this

is going to be the "id"  and then we're going to set of hard-coding to 2,000

we're going to call this "sleepTime" and then we're going to format

this Console.WriteLine with the id as well.




And now in our lambda expression up here

we can get rid of these curly braces since we're really going to call one

method here and it;s going to do some very important work

in this task is the only job of this task and we're going to call the ID 1

and sleep time fifteen hundred milliseconds  for a second and a half so

there we go save this week if we have five we should see

the same basic functionality

so nothing here to out of the ordinary





第二階段 練習code


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

namespace Task_Parallel_Library
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Task(() => DosomeVeryImportantWork(1, 1500));
            t1.Start();
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }

        static void DosomeVeryImportantWork(int id,int sleepTime)
        {
            Console.WriteLine("task {0} is beginning",id);
            Thread.Sleep(1000);
            Console.WriteLine("task {0} has completed",id);
        }
    }
}
//

So now what I would like to do is

I would like to show you how these things begin to execute in parallel

given the opportunity


we can try to copy these two lines I'm going to copy

and paste two moree of them here so now

I'm going to have the t2 and t3 to do some very important work

this is going to have an id of 2 and 3

and instead of waiting the same time this one's going to execute in three seconds

and the third one is going to execute in merely one second











you can see different output results   !!




第三階段 練習code


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

namespace Task_Parallel_Library
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Task(() => DosomeVeryImportantWork(1, 1500));
            t1.Start();
            var t2 = new Task(() => DosomeVeryImportantWork(2, 3000));
            t2.Start();
            var t3 = new Task(() => DosomeVeryImportantWork(3, 1000));
            t3.Start();
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();
        }

        static void DosomeVeryImportantWork(int id,int sleepTime)
        {
            Console.WriteLine("task {0} is beginning",id);
            Thread.Sleep(1000);
            Console.WriteLine("task {0} has completed",id);
        }
    }
}
//







學習參考用的  Youtube 影片

=====================================================================

Advanced C#: 14 Task Parallel Library

https://www.youtube.com/watch?v=gfkuD_eWM5Y


Getting Started with Lambda Expressions with Jeremy Clark

https://www.youtube.com/watch?v=xev-kNmz_a0


C# lambda expression as a function


https://www.youtube.com/watch?v=ooHyzbtr12w






學習引用資料的 來源 Blog

=====================================================================

C# Task 用法

http://www.wxzzz.com/683.html

Hacking C#’s Lambda Expressions Into Hash Rockets

https://joelholder.com/2013/07/19/hacking-cs-lambda-expressions-into-hash-rockets/


C# 學習筆記:多執行緒 (6) - TPL

http://huan-lin.blogspot.com/2013/06/csharp-notes-multithreading-6-tpl.html


[最多推薦]5天玩轉C#並行和多線程編程 —— 第三天 認識和使用Task(15/1539)

https://wefollownews.appspot.com/cittopnews201408_19/8019.html


C#線程篇---你所不知道的線程池

https://read01.com/EmEBDo.html

Thread Pooling in C#

http://www.c-sharpcorner.com/uploadfile/1d42da/threading-pooling-in-c-sharp/

Go Parallel with .NET 4.0 Parallel Extensions

http://udooz.net/blog/2009/08/parallel-programming-net-4-0-using-task/


新手淺談Task異步編程和Thread多線程編程

http://www.xlgps.com/article/215391.html


Processing streaming data with a thread pool

https://www.classes.cs.uchicago.edu/archive/2013/spring/12300-1/pa/pa2/


THREADS VS TASKS IN C#

http://jviaches.blogspot.tw/2015/07/threads-vs-tasks.html


英文片語 “Kind of / Sort of” 到底表示什麼意義?

http://english.ecominfozone.net/archives/4923


留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header