C# 使用任务(TPL)库是否使应用程序成为多线程的?
最近在接受采访时,我得到了这个问题 问:您编写过多线程应用程序吗 A:是的 问:想解释一下吗 答:我使用C# 使用任务(TPL)库是否使应用程序成为多线程的?,c#,multithreading,.net-4.0,task-parallel-library,multitasking,C#,Multithreading,.net 4.0,Task Parallel Library,Multitasking,最近在接受采访时,我得到了这个问题 问:您编写过多线程应用程序吗 A:是的 问:想解释一下吗 答:我使用任务(任务并行库)来执行一些任务,比如在加载UI时等待来自internet的一些信息。这提高了我的应用程序的可用性 问:但是,仅仅您使用了TPL就意味着您已经编写了一个多线程应用程序 我:(不知道该说什么) 那么,什么是多线程应用程序呢?它与使用任务不同吗?A任务是对未来工作的承诺。使用它时,您可以将它用于基于I/O的工作,而不需要使用多个线程来执行代码。一个很好的例子是将C#5的async/
任务
(任务并行库)来执行一些任务,比如在加载UI时等待来自internet的一些信息。这提高了我的应用程序的可用性
问:但是,仅仅您使用了TPL
就意味着您已经编写了一个多线程
应用程序
我:(不知道该说什么)
那么,什么是多线程应用程序呢?它与使用任务
不同吗?A任务
是对未来工作的承诺。使用它时,您可以将它用于基于I/O的
工作,而不需要使用多个线程来执行代码。一个很好的例子是将C#5的async/await
特性与HttpClient
一起使用,它可以进行基于网络的I/O工作
但是,您可以利用TPL
来执行多线程工作。例如,当使用Task.Run
或Task.Factory.Startnew
启动新任务时,后台工作会在ThreadPool
上排队等待您,而TPL
会为我们抽象出线程池,允许您使用多个线程
使用多线程的一个常见场景是当您有CPU限制的工作可以同时(并行)完成时。使用多线程应用程序需要承担很大的责任
所以我们看到,使用TPL
并不一定意味着使用多线程,但您肯定可以利用它来执行多线程
问:但是,你使用TPL就意味着你写了一个
多线程应用程序
聪明的问题,任务!=使用多线程,您可以创建一个任务
,该任务本身可以在单个线程(可能仅是UI线程)中执行
任务
只是对可能在将来完成的操作的抽象。这并不意味着代码是多线程的。通常,任务
涉及多线程,但不一定总是这样
请记住,只有掌握了TPL
的知识,您才能说您了解多线程。您需要涵盖许多概念
- 线
- 同步原语
- 线程安全
- 异步编程
- 并行编程是第三方物流的一部分
- 还有更多
当然还有任务并行库
注意:这不是完整的列表,这些只是我的想法
学习资源:
我建议单就线程而言
对于视频教程,我建议。它是有报酬的,但值得付出代价
最后但并非最不重要的一点:是的,当然是这样。任务可以用来表示在多个线程上进行的操作,但它们不必这样做。可以编写只在单个线程中执行的复杂TPL应用程序。例如,当您有一个任务表示对某些数据的网络请求时,该任务不会创建额外的线程来实现该目标。这样的程序(希望)是异步的,但不一定是多线程的
并行性是在同一时间做不止一件事。这可能是多线程的结果,也可能不是
我们来做个类比
以下是鲍勃如何烹调晚餐:
他把一壶水倒满,然后煮开
然后他把意大利面放入水中
面食吃完后,他把它吸干
他准备酱汁的配料
他把酱汁的所有原料都放在平底锅里
他煮酱汁
他把酱汁放在意大利面上
他吃晚饭
Bob做饭时完全同步,没有多线程、异步或并行
以下是简做晚餐的方式:
她把一壶水倒满,开始煮
她准备酱汁的配料
她把意大利面放在沸水里
她把配料放在平底锅里
她喝干了面食
她把酱汁放在面食上
她吃晚饭
Jane利用异步烹饪(没有任何多线程)在烹饪晚餐时实现并行性
下面是Servy如何烹饪晚餐:
他告诉鲍勃烧一壶水,准备好后放入意大利面,然后端上意大利面
他告诉简准备酱汁的原料,烹饪,然后在面食上食用
他等鲍勃和简说完
他吃晚饭
Servy利用了多个线程(工作线程),每个线程(工作线程)分别同步地完成各自的工作,但彼此异步地工作以实现并行性
当然,如果我们考虑,例如,我们的炉子有两个燃烧器,或者只有一个,这就更有趣了。如果我们的炉子有两个燃烧器,那么我们的两条线,鲍勃和简,都能在不妨碍彼此的情况下完成工作。他们可能会撞上一些肩膀,或者时不时地试图从同一个柜子里抓东西,所以他们会放慢速度,但不会太慢。但是,如果他们每个人都需要共用一个炉灶,那么无论其他人何时在工作,他们实际上都无法完成很多工作。在这种情况下,这项工作实际上不会比让一个人完全同步做饭更快,就像鲍勃独自做饭时那样。在本例中,我们使用多个线程进行烹饪,但我们的烹饪不是并行的。并非所有多线程工作实际上都是并行工作。这就是在一台机器上运行多个线程时发生的情况
public class Bob : ICook
{
public IMeal Cook()
{
Pasta pasta = PastaCookingOperations.MakePasta();
Sauce sauce = PastaCookingOperations.MakeSauce();
return PastaCookingOperations.Combine(pasta, sauce);
}
}
public class Jane : ICook
{
public IMeal Cook()
{
Task<Pasta> pastaTask = PastaCookingOperations.MakePastaAsync();
Task<Sauce> sauceTask = PastaCookingOperations.MakeSauceAsync();
return PastaCookingOperations.Combine(pastaTask.Result, sauceTask.Result);
}
}
public class Servy : ICook
{
public IMeal Cook()
{
var bobsWork = Task.Run(() => PastaCookingOperations.MakePasta());
var janesWork = Task.Run(() => PastaCookingOperations.MakeSauce());
return PastaCookingOperations.Combine(bobsWork.Result, janesWork.Result);
}
}
async static Task TestAsync()
{
Func<Task> doAsync = async () =>
{
await Task.Delay(1).ConfigureAwait(false);
Console.WriteLine(new { Thread.CurrentThread.ManagedThreadId });
};
var tasks = Enumerable.Range(0, 10).Select(i => doAsync());
await Task.WhenAll(tasks);
}
// ...
TestAsync().Wait();