当前位置: 首页 > 知识库问答 >
问题:

使用任务(TPL)库会使应用程序成为多线程的吗?

公孙令秋
2023-03-14

最近在接受采访时,我得到了这个问题。

Q: 您编写过多线程应用程序吗?

甲:是的

问:介意解释更多吗?

答:我使用了< code>Tasks(任务并行库)来执行一些任务,比如< code >加载UI时等待来自互联网的一些信息。这提高了我的应用程序的可用性。

问:但是,仅仅您使用了TPL就意味着您编写了多线程应用程序?

我:(不知道该说什么)

那么,究竟什么是多线程应用程序?它与使用任务不同吗?

共有3个答案

须旭
2023-03-14

问:但是,只是你使用了TPL就意味着你编写了一个多线程应用程序

聪明的问题,任务!=多线程,使用TaskCompletionSource,您可以创建一个任务,该任务可以在单线程(可能仅是UI线程)中执行。

任务只是对未来可能完成的操作的抽象。这并不意味着代码是多线程的。通常,任务涉及多线程,但不一定总是这样。

请记住,仅具备< code>TPL的知识,您不能说您了解多线程。有许多概念你需要涵盖。

  • 线
  • 同步原语
  • Thread安全
  • 异步编程
  • 并行编程,这是TPL的一部分。
  • 还有更多...

当然还有任务并行库。

注意:这不是完整的列表,这些只是从我的头顶。

  • Eric的旧博客
  • Eric的新博客
  • 斯蒂芬·图布的博客

单独穿线,我建议http://www.albahari.com/threading/

对于视频教程,我建议使用Pluralsight。它是付费的,但值得付出代价。

最后但并非最不重要的一点:当然,这是Stackoverflow。

司马钱明
2023-03-14

任务是对未来工作完成的promise。使用它时,您可以将其用于基于I/O的工作,这不需要您使用多个线程执行代码。一个很好的例子是将C#5的async/wait特性与HttpClient一起使用,后者执行基于网络的I/O工作。

但是,您可以利用TPL来执行多线程工作。例如,当使用<code>任务时。运行或<code>Task.Factory。Startnew要开始一项新任务,幕后工作将在<code>线程池

使用多线程的常见场景是当您有可以同时(并行)完成的CPU限制工作时。使用多线程应用程序需要承担很大的责任。

因此,我们看到,使用< code>TPL并不一定意味着使用多线程,但是您肯定可以利用它来执行多线程。

汲品
2023-03-14

任务可以用来表示发生在多个线程上的操作,但它们不必这样做。人们可以编写只在单个线程中执行的复杂TPL应用程序。例如,当您有一个任务,它代表对某些数据的网络请求时,该任务不会创建额外的线程来实现该目标。这样的程序(希望)是异步的,但不一定是多线程的。

并行就是同时做多件事。这可能是也可能不是多线程的结果。

我们来打个比方。

鲍勃是这样做晚餐的:

    < li >他倒了一壶水,把它烧开。 < li >然后,他将意大利面放入水中。 < li >煮好后,他将意大利面沥干。 < li >他准备酱汁的配料。 < li >他将酱汁的所有配料放入平底锅中。 < li >他煮他的酱。 < li >他把调味汁放在意大利面上。 < li >他吃晚饭。

Bob做饭时完全同步,没有多线程、异步或并行。

简是这样做饭的:

  1. 她装满一壶水,开始煮
  2. 她准备酱汁的原料
  3. 她把意大利面放在开水里
  4. 她把配料放进平底锅里
  5. 她喝干了意大利面
  6. 她把酱汁放在意大利面上
  7. 她吃晚饭

Jane利用异步烹饪(没有任何多线程)在烹饪晚餐时实现并行。

Servy是这样做晚餐的:

  1. 他告诉鲍勃煮一壶水,准备好后放进意大利面,然后上菜。
  2. 他告诉简准备酱汁的配料,煮熟,然后在完成后将其放在意大利面上。
  3. 他等待鲍勃和简完成。
  4. 他吃他的晚餐。

Servy利用了多个线程(工作线程),每个线程都单独同步地工作,但它们彼此异步地工作以实现并行性。

当然,如果我们考虑,例如,我们的炉子是有两个燃烧器还是只有一个燃烧器,这会变得更加有趣。如果我们的炉子有两个燃烧器,那么我们的两个线程,鲍勃和简,都能够在不妨碍彼此的情况下完成工作。他们可能会有点撞肩膀,或者时不时地从同一个柜子里抓东西,所以他们会放慢速度,但不会太慢。但是,如果他们每个人都需要共用一个炉灶,那幺当其他人在工作时,他们实际上根本无法完成很多工作。在这种情况下,这项工作实际上不会比让一个人完全同步做饭更快,就像鲍勃独自做饭一样。在本例中,我们使用多个线程进行烹饪,但我们的烹饪不是并行的。并非所有多线程工作实际上都是并行工作。当您在一台具有一个CPU的机器上运行多个线程时,会发生这种情况。实际上,只使用一个线程并不能更快地完成工作,因为每个线程只是轮流工作。(这并不意味着多线程程序在单核CPU上毫无意义,它们不是,只是使用它们的原因不是为了提高速度。)

我们甚至可以考虑这些厨师将如何使用任务并行库来完成他们的工作,以查看TPL的哪些用途对应于这些类型的厨师:

首先,我们有bob,只需编写正常的非TPL代码,并同步执行所有操作:

public class Bob : ICook
{
    public IMeal Cook()
    {
        Pasta pasta = PastaCookingOperations.MakePasta();
        Sauce sauce = PastaCookingOperations.MakeSauce();
        return PastaCookingOperations.Combine(pasta, sauce);
    }
}

然后我们有Jane,她启动了两个不同的异步操作,然后在启动每个操作后等待它们来计算她的结果。

public class Jane : ICook
{
    public IMeal Cook()
    {
        Task<Pasta> pastaTask = PastaCookingOperations.MakePastaAsync();
        Task<Sauce> sauceTask = PastaCookingOperations.MakeSauceAsync();
        return PastaCookingOperations.Combine(pastaTask.Result, sauceTask.Result);
    }
}

作为这里的提醒,Jane 正在使用 TPL,并且她正在并行执行大部分工作,但她只使用单个线程来完成她的工作。

然后我们有Servy,他使用< code>Task。运行以创建一个表示在另一个线程中工作的任务。他启动两个不同的工人,让他们同步做一些工作,然后等待两个工人都完成。

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);
    }
}
 类似资料:
  • 我正在编写一个程序,演示在服务器可伸缩性上下文中使用异步IO的好处。程序并发地使用一个异步方法,然后报告参与异步处理的线程的ID。 为了说明,请考虑以下内容: 在同一上下文中调用时,输出结果完全不同。这些任务通常需要更长的时间来执行,并且唯一线程ID的总数通常在30个左右(同样,对于我的2核机器)。 为什么会出现这种差距呢?我知道不是的普通包装,但是线程池是共同的分母,我希望在TPL实现中也能出现

  • 我有一个包含“资源管理器”类的多线程Java应用程序。 此类提供了一个资源列表,这些资源可以作为初始化参数请求。然后检查每个文件的本地文件系统,并将确定为本地的文件添加到列表中。 当类收到资源请求时,会发生以下情况之一: > 如果资源被确定为本地资源(在列表中):请提供可以找到它的URI。 如果资源是远程的(不在列表中):安排一个工作进程来获取资源。工作进程将在任务完成时通知经理,并更新本地资源列

  • 我一直在学习JavaFX的任务,并使用这些任务通过或任务的方法等与应用程序线程进行通信。但是,我的需要知道用户何时按下 GUI 上的按钮,因为这可能会更改任务的 方法需要返回的值。我该怎么做?我知道如何响应单线程应用程序上的按钮按下事件,但不确定如何以线程安全的方式处理它。 到目前为止,这是我所拥有的,这是实现按钮事件的明智方式吗?

  • 问题内容: 我最近继承了一个小型Java程序,该程序从大型数据库中获取信息,进行一些处理并生成有关该信息的详细图像。原始作者使用单个线程编写了代码,然后对其进行了修改,以使其可以使用多个线程。 他在代码中定义了一个常量; 然后,它设置用于创建映像的线程数。 我理解他的理由,即线程数不能大于可用处理器的数目,因此将其设置为可以充分发挥处理器潜力的数量。这样对吗?还是有更好的方法来充分利用处理器的潜力

  • 我有一个类,它基本上会做两次相同的步骤。听起来像是一个在哪里多线程处理程序的完美例子。我的问题是,如果我只需要两个线程就可以做到这一点。以下是一般情况 我已经完成了第一部分——构建对象——的工作。我现在的问题是- 如何让主线程等待两个线程完成其第一部分?也许main会在两个对象上执行等待,然后在线程notifyAll之后,它们会在主线程上执行等待?但是线程如何抓住主线程呢?也许用这个 我怎样才能在

  • 问题内容: 我正在尝试将Hibernate用于多线程应用程序,其中每个线程都检索一个对象并将其插入表中。我的代码如下所示。我每个线程都有本地hibernate会话对象,在每个InsertData中,我都执行beginTransaction和commit。 我面临的问题是很多次我收到“ org.hibernate.TransactionException:不支持嵌套事务” 由于我是hibernate