快捷搜索:
来自 计算机编程 2019-08-24 18:08 的文章
当前位置: 67677新澳门手机版 > 计算机编程 > 正文

Net异步实例讲解,的那些事儿

 1.2 信号量(Semaphore)

 塞马phore负担和煦线程,能够界定对某一能源访谈的线程数量

 这里对SemaphoreSlim类的用法做一个简易的例子:

67677新澳门手机版 1

static SemaphoreSlim semLim = new SemaphoreSlim(3); //3表示最多只能有三个线程同时访问
static void Main(string[] args)
{
    for (int i = 0; i < 10; i  )
    {
        new Thread(SemaphoreTest).Start();
    }
    Console.Read();
}
static void SemaphoreTest()
{
    semLim.Wait();
    Console.WriteLine("线程"   Thread.CurrentThread.ManagedThreadId.ToString()   "开始执行");
    Thread.Sleep(2000);
    Console.WriteLine("线程"   Thread.CurrentThread.ManagedThreadId.ToString()   "执行完毕");
    semLim.Release();
}

67677新澳门手机版 2

实行结果如下:

67677新澳门手机版 367677新澳门手机版 4

可以见见,刚先导独有五个线程在推行,当贰个线程试行实现并释放之后,才会有新的线程来推行措施!

除去SemaphoreSlim类,还足以使用Semaphore类,以为更灵敏,感兴趣的话能够搜一下,这里就不做示范了!

2.Task

Task是.NET4.0参预的,跟线程池ThreadPool的成效看似,用Task开启新职务时,会从线程池中调用线程,而Thread每回实例化都会创立多个新的线程。

Console.WriteLine("主线程启动");
//Task.Run启动一个线程
//Task启动的是后台线程,要在主线程中等待后台线程执行完毕,可以调用Wait方法
//Task task = Task.Factory.StartNew(() => { Thread.Sleep(1500); Console.WriteLine("task启动"); });
Task task = Task.Run(() => { 
    Thread.Sleep(1500);
    Console.WriteLine("task启动");
});
Thread.Sleep(300);
task.Wait();
Console.WriteLine("主线程结束");

执行结果如下:

67677新澳门手机版 5

翻开新职分的主意:Task.Run()可能Task.Factory.StartNew(),开启的是后台线程

要在主线程中等待后台线程实施实现,可以选拔Wait方法(会以联合的点子来试行)。不用Wait则会以异步的主意来试行。

正如一下Task和Thread:

static void Main(string[] args)
{
    for (int i = 0; i < 5; i  )
    {
        new Thread(Run1).Start();
    }
    for (int i = 0; i < 5; i  )
    {
        Task.Run(() => { Run2(); });
    }
}
static void Run1()
{
    Console.WriteLine("Thread Id ="   Thread.CurrentThread.ManagedThreadId);
}
static void Run2()
{
    Console.WriteLine("Task调用的Thread Id ="   Thread.CurrentThread.ManagedThreadId);
}

实践结果:

67677新澳门手机版 6

能够看出来,直接用Thread会开启5个线程,用Task(用了线程池)开启了3个!

1.1 线程池

试想一下,要是有多量的职分急需管理,比方网址后台对于HTTP诉求的处理,那是还是不是要对每种伸手制造多少个后台线程呢?分明不合适,那会占有多量内部存款和储蓄器,何况多次地创立的长河也会严重影响速度,那怎么做吧?线程池正是为着缓慢解决这一难题,把创设的线程存起来,形成一个线程池(里面有多个线程),当要处理任务时,若线程池中有空暇线程(前一个职责实行到位后,线程不会被回收,会被安装为空闲状态),则直接调用线程池中的线程实施(例asp.net管理机制中的Application对象),

采用事例:

67677新澳门手机版 7

for (int i = 0; i < 10; i  )
{
    ThreadPool.QueueUserWorkItem(m =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
    });
}
Console.Read();

67677新澳门手机版 8

运行结果:

67677新澳门手机版 9

能够看来,即使进行了十四回,但并未创制11个线程。

2.1 Task<TResult>

Task<TResult>就是有再次回到值的Task,TResult正是回来值类型。

Console.WriteLine("主线程开始");
//返回值类型为string
Task<string> task = Task<string>.Run(() => {
    Thread.Sleep(2000); 
    return Thread.CurrentThread.ManagedThreadId.ToString(); 
});
//会等到task执行完毕才会输出;
Console.WriteLine(task.Result);
Console.WriteLine("主线程结束");

运行结果:

67677新澳门手机版 10

通过task.Result能够取到再次来到值,若取值的时候,后台线程还没推行完,则会等待其实施达成!

简轻松单提一下:

Task义务可以因此CancellationTokenSource类来撤除,感觉用得相当的少,用法比较轻巧,感兴趣的话能够搜一下!

2.Task

Task是.NET4.0参加的,跟线程池ThreadPool的效果类似,用Task开启新任务时,会从线程池中调用线程,而Thread每一次实例化都会成立二个新的线程。

67677新澳门手机版 11

Console.WriteLine("主线程启动");
//Task.Run启动一个线程
//Task启动的是后台线程,要在主线程中等待后台线程执行完毕,可以调用Wait方法
//Task task = Task.Factory.StartNew(() => { Thread.Sleep(1500); Console.WriteLine("task启动"); });
Task task = Task.Run(() => { 
    Thread.Sleep(1500);
    Console.WriteLine("task启动");
});
Thread.Sleep(300);
task.Wait();
Console.WriteLine("主线程结束");

67677新澳门手机版 12

实践结果如下:

67677新澳门手机版 13

拉开新职分的办法:Task.Run()只怕Task.Factory.StartNew(),开启的是后台线程

要在主线程中等待后台线程实施完结,能够动用Wait方法(会以三只的法子来实施)。不用Wait则会以异步的办法来实践。

正如一下Task和Thread:

67677新澳门手机版 14

static void Main(string[] args)
{
    for (int i = 0; i < 5; i  )
    {
        new Thread(Run1).Start();
    }
    for (int i = 0; i < 5; i  )
    {
        Task.Run(() => { Run2(); });
    }
}
static void Run1()
{
    Console.WriteLine("Thread Id ="   Thread.CurrentThread.ManagedThreadId);
}
static void Run2()
{
    Console.WriteLine("Task调用的Thread Id ="   Thread.CurrentThread.ManagedThreadId);
}

67677新澳门手机版 15

实践结果:

67677新澳门手机版 16

能够看出来,直接用Thread会开启5个线程,用Task(用了线程池)开启了3个!

1.线程(Thread)

多线程的含义在于贰个应用程序中,有多个实践部分能够同不经常间实行;对于相比较耗费时间的操作(举例io,数据库操作),或许等待响应(如WCF通讯)的操作,能够单独开启后台线程来施行,那样主线程就不会阻塞,能够继续往下推行;等到后台线程试行达成,再通报主线程,然后做出相应操作!

在C#中拉开新线程相比较轻松

static void Main(string[] args)
{
    Console.WriteLine("主线程开始");
    //IsBackground=true,将其设置为后台线程
    Thread t = new Thread(Run) { IsBackground = true };
    t.Start();
   Console.WriteLine("主线程在做其他的事!");
    //主线程结束,后台线程会自动结束,不管有没有执行完成
    //Thread.Sleep(300);
    Thread.Sleep(1500);
    Console.WriteLine("主线程结束");
}
static void Run()
{
    Thread.Sleep(700);
    Console.WriteLine("这是后台线程调用");
}

 试行结果如下图,

67677新澳门手机版 17

可以见见在开发银行后台线程之后,主线程继续往下实行了,并从未等到后台线程施行完以后。

6.异步的回调

文中全部Task<TResult>的重临值都是直接用task.result获取,这样一旦后台职务未有施行完结的话,主线程会等待其举行完结,那样的话就和一同一样了(看上去同样,但实际上await的时候并不会招致线程的梗塞,web程序感到不到,可是wpf,winform那样的桌面程序若不使用异步,会导致UI线程的鸿沟)。轻便演示一下Task回调函数的利用:

67677新澳门手机版 18

Console.WriteLine("主线程开始");
Task<string> task = Task<string>.Run(() => {
    Thread.Sleep(2000); 
    return Thread.CurrentThread.ManagedThreadId.ToString(); 
});
//会等到任务执行完之后执行
task.GetAwaiter().OnCompleted(() =>
{
    Console.WriteLine(task.Result);
});
Console.WriteLine("主线程结束");
Console.Read();

67677新澳门手机版 19

实践结果:

67677新澳门手机版 20

OnCompleted中的代码会在任务实践到位之后实行!

除此以外task.ContinueWith()也是叁个着重的秘诀:

67677新澳门手机版 21

Console.WriteLine("主线程开始");
Task<string> task = Task<string>.Run(() => {
    Thread.Sleep(2000); 
    return Thread.CurrentThread.ManagedThreadId.ToString(); 
});

task.GetAwaiter().OnCompleted(() =>
{
    Console.WriteLine(task.Result);
});
task.ContinueWith(m=>{Console.WriteLine("第一个任务结束啦!我是第二个任务");});
Console.WriteLine("主线程结束");
Console.Read();

67677新澳门手机版 22

实行结果:

67677新澳门手机版 23

ContinueWith()方法能够让该后台线程继续试行新的义务。

1.1 线程池

试想一下,假诺有多量的天职须要管理,比方网址后台对于HTTP恳求的拍卖,那是否要对每三个呼吁创制七个后台线程呢?明显不合适,这会据有多量内部存款和储蓄器,并且数11处处创造的经过也会严重影响进程,那如何做呢?线程池便是为了消除这一标题,把创造的线程存起来,变成三个线程池(里面有八个线程),当要拍卖职分时,若线程池中有闲暇线程(前三个职分奉行到位后,线程不会被回收,会棉被服装置为空闲状态),则直接调用线程池中的线程推行(例asp.net管理体制中的Application对象),

利用事例:

for (int i = 0; i < 10; i  )
{
    ThreadPool.QueueUserWorkItem(m =>
    {
        Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
    });
}
Console.Read();

运作结果:

67677新澳门手机版 24

能够看来,尽管实施了14回,但并从未开创11个线程。

67677新澳门手机版 ,1.线程(Thread)

多线程的含义在于三个应用程序中,有七个施行部分能够并且实行;对于相比较耗费时间的操作(举例io,数据库操作),或许等待响应(如WCF通讯)的操作,能够单独开启后台线程来举行,那样主线程就不会阻塞,能够一连往下推行;等到后台线程试行已毕,再公告主线程,然后做出相应操作!

在C#中展开新线程比较简单

67677新澳门手机版 25

static void Main(string[] args)
{
    Console.WriteLine("主线程开始");
    //IsBackground=true,将其设置为后台线程
    Thread t = new Thread(Run) { IsBackground = true };
    t.Start();
   Console.WriteLine("主线程在做其他的事!");
    //主线程结束,后台线程会自动结束,不管有没有执行完成
    //Thread.Sleep(300);
    Thread.Sleep(1500);
    Console.WriteLine("主线程结束");
}
static void Run()
{
    Thread.Sleep(700);
    Console.WriteLine("这是后台线程调用");
}

67677新澳门手机版 26

 施行结果如下图,

67677新澳门手机版 27

能够看来在开发银行后台线程之后,主线程继续往下推行了,并不曾等到后台线程推行完事后。

 1.2 信号量(Semaphore)

 Semaphore肩负协和线程,能够限制对某一能源访谈的线程数量

 这里对SemaphoreSlim类的用法做四个简练的例证:

static SemaphoreSlim semLim = new SemaphoreSlim(3); //3表示最多只能有三个线程同时访问
static void Main(string[] args)
{
    for (int i = 0; i < 10; i  )
    {
        new Thread(SemaphoreTest).Start();
    }
    Console.Read();
}
static void SemaphoreTest()
{
    semLim.Wait();
    Console.WriteLine("线程"   Thread.CurrentThread.ManagedThreadId.ToString()   "开始执行");
    Thread.Sleep(2000);
    Console.WriteLine("线程"   Thread.CurrentThread.ManagedThreadId.ToString()   "执行完毕");
    semLim.Release();
}

执行结果如下:

67677新澳门手机版 2867677新澳门手机版 29

能够见见,刚初始仅有八个线程在进行,当一个线程实践完结并释放之后,才会有新的线程来进行格局!

除去SemaphoreSlim类,还能运用Semaphore类,感到更加灵敏,感兴趣的话能够搜一下,这里就不做示范了!

本文由67677新澳门手机版发布于计算机编程,转载请注明出处:Net异步实例讲解,的那些事儿

关键词: