Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步编程和多线程之间的区别是什么?_C#_Multithreading_Asynchronous_Parallel Processing_Async Await - Fatal编程技术网

C# 异步编程和多线程之间的区别是什么?

C# 异步编程和多线程之间的区别是什么?,c#,multithreading,asynchronous,parallel-processing,async-await,C#,Multithreading,Asynchronous,Parallel Processing,Async Await,我认为它们基本上是一样的——编写在处理器之间分割任务的程序(在有2个以上处理器的机器上)。然后我在读,上面写着: 异步方法旨在成为非阻塞操作。等待 异步方法中的表达式在 等待的任务正在运行。取而代之的是,这个表达式表示其余的 将方法的 异步方法 async和await关键字不会导致添加额外的线程 创建。异步方法不需要多线程,因为异步 方法不在自己的线程上运行。该方法在当前服务器上运行 同步上下文,并且仅当 方法处于活动状态。您可以使用Task.Run将CPU绑定的工作移动到 后台线程,但后台线程

我认为它们基本上是一样的——编写在处理器之间分割任务的程序(在有2个以上处理器的机器上)。然后我在读,上面写着:

异步方法旨在成为非阻塞操作。等待 异步方法中的表达式在 等待的任务正在运行。取而代之的是,这个表达式表示其余的 将方法的 异步方法

async和await关键字不会导致添加额外的线程 创建。异步方法不需要多线程,因为异步 方法不在自己的线程上运行。该方法在当前服务器上运行 同步上下文,并且仅当 方法处于活动状态。您可以使用Task.Run将CPU绑定的工作移动到 后台线程,但后台线程对进程没有帮助 那只是等待结果出来

我想知道是否有人能帮我翻译成英语。它似乎区分了异步性(这是一个词吗?)和线程,并暗示您可以有一个具有异步任务但没有多线程的程序

现在我理解了异步任务的概念,比如Jon Skeet的《C#In Depth》(第三版)第467页的例子

,因为
DisplayWebsiteLength()
x
y
无关,将导致
DisplayWebsiteLength()
在“后台”执行,如

显然,这是一个愚蠢的例子,但我是对的,还是完全糊涂了


(另外,我很困惑为什么在上述函数的主体中没有使用
sender
e

您的误解非常普遍。许多人被教导多线程和异步是一回事,但事实并非如此

打个比方通常会有帮助。你在餐馆里做饭。来了一份鸡蛋和吐司的订单

  • 你先煮鸡蛋,然后烤面包
  • 异步、单线程:启动鸡蛋烹饪并设置计时器。你开始烤面包,并设置计时器。他们都在做饭的时候,你打扫厨房。当计时器响时,你把鸡蛋从火上拿下来,把吐司从烤面包机里拿出来端上桌
  • 异步、多线程:你又雇了两个厨师,一个做鸡蛋,一个做吐司。现在的问题是如何协调厨师,以便他们在共享资源时不会在厨房内发生冲突。你必须付钱给他们
多线程只是异步的一种,这有意义吗线程是关于工人的;异步是关于任务的。在多线程工作流中,您将任务分配给工人。在异步单线程工作流中,您有一个任务图,其中一些任务依赖于其他任务的结果;在每个任务完成时,它会调用代码,根据刚刚完成的任务的结果,安排可以运行的下一个任务。但是您(希望)只需要一个工人来执行所有任务,而不是每个任务一个工人

这将有助于认识到许多任务不受处理器限制。对于处理器限制的任务,雇佣尽可能多的工作人员(线程)是有意义的,为每个工作人员分配一个任务,为每个工作人员分配一个处理器,让每个处理器只做尽快计算结果的工作。但对于不在处理器上等待的任务,您根本不需要分配工作人员。您只需等待结果可用的消息到达,并在等待时执行其他操作。当该消息到达时,您可以将继续完成的任务安排为您的待办事项列表上的下一件要检查的事情

让我们更详细地看一下Jon的例子。会发生什么

  • 有人调用DisplayWebSiteLength。谁我们不在乎
  • 它设置一个标签,创建一个客户机,并要求客户机获取一些东西。客户机返回一个对象,该对象表示获取某物的任务。这项任务正在进行中
  • 它正在另一个线程上进行吗?可能不会。阅读为什么没有线程
  • 现在我们在等待任务。会发生什么?我们检查任务是否在创建它和等待它之间完成。如果是,则获取结果并继续运行。让我们假设它还没有完成我们将此方法的剩余部分注册为该任务的继续,并返回
  • 现在,控件已返回调用方。它有什么作用?不管它想要什么
  • 现在假设任务完成。它是怎么做到的?可能它正在另一个线程上运行,或者可能是我们刚刚返回的调用方允许它在当前线程上运行到完成。不管怎样,我们现在已经完成了一项任务
  • 完成的任务要求正确的线程(可能也是唯一的线程)运行任务的继续
  • 控件立即返回到我们刚才在等待点离开的方法中。现在有了一个可用的结果,因此我们可以分配
    text
    并运行该方法的其余部分

这就像我的类比。有人向你要一份文件。你把文件寄出去,然后继续做其他的工作。当邮件到达时,你会收到信号,当你喜欢的时候,你会完成剩下的工作流程——打开信封,支付投递费,等等。您不需要雇佣其他工人来为您完成所有这些工作。

在浏览器中,Javascript是无线程异步程序的一个很好的例子

您不必担心多段代码同时接触相同的对象:每个函数将在任何其他javasc之前完成运行
async void DisplayWebsiteLength ( object sender, EventArgs e )
{
    label.Text = "Fetching ...";
    using ( HttpClient client = new HttpClient() )
    {
        Task<string> task = client.GetStringAsync("http://csharpindepth.com");
        string text = await task;
        label.Text = text.Length.ToString();
    }
}
int x = 5; 
DisplayWebsiteLength();
double y = Math.Pow((double)x,2000.0);
                processor 1                |      processor 2
-------------------------------------------------------------------
int x = 5;                                 |  DisplayWebsiteLength()
double y = Math.Pow((double)x,2000.0);     |