我可以在GUI应用程序中看到新的async和await关键字的用处,其中添加一个线程来进行一些计算是必要的,新的关键字真的很容易。但是其他类型的应用呢?
例如,执行某些工作的服务器或不断处理数据的进程?可能我仍然误解新关键字,但是这些类型的应用程序是否会从新关键字中受益,还是我们应该继续使用Tasks来实现更明确的多线程?
答案 0 :(得分:2)
在非GUI应用程序中,使用await
的主要优点是在进行I / O时。
如果您正在使用“旧方式”,那么您将使用I / O的同步方法,在它们工作时阻塞线程。使用await
,你没有阻塞一个线程,这意味着syour应用程序将使用更少的线程,这可能导致更低的内存使用量(每个线程需要1 MB的内存)和整体更好的性能。
使用旧的异步编程模型可以实现类似的改进,但它更加麻烦。
如果您不关心非GUI应用程序使用的线程多于必要的线程,那么await
对您的使用并不多。但如果你关心这一点,await
可以帮助你很多。
答案 1 :(得分:1)
await
和async
互补任务。
您仍然应该使用任务,但使用await
和async
只会使asynchronous methods的编写更容易。
答案 2 :(得分:1)
例如,执行某些工作的服务器或持续处理数据的进程?
这在这里非常合适。例如,在WCF服务中,您可以使用async和await在单个异步请求中组合多个异步服务请求而不会阻塞。
我可能仍然误解新关键字,但这些类型的应用程序是否会从新关键字中受益,还是应该继续使用Tasks来实现更明确的多线程?
两人一起工作,非常好。 Async和await经常使用Task
和Task<T>
来处理和组合多个操作,这些操作要简单得多。
但是,在“最低级别”,创建实际Task
的代码可能会使用相同的基于TPL的技术。一旦你有方法创建一个Task
,异步并等待使用该方法(包括使用它来制作更多异步方法,或使用它来制作同时运行多个任务的方法)简单。
答案 3 :(得分:1)
任何时候你计划调用一个最终会异步运行的方法,而不会阻塞,并且你将拥有一个回调方法,你可以使用新的关键字来简化这种语法。如果您没有任何回调代码并且没有遵循继续传递编程风格,那么新关键字可能无法帮助您。 (这并不是说你不能使用它们,如果你真的......真的很想。)
答案 4 :(得分:0)
几个月前,当我第一次开始使用TAP时,我对同样的问题进行了捣乱,并得出结论认为TAP可以在并发的“类似服务器”的情况下很好地工作,而不必“下拉”到更多的第三方物流的细节区域例如,执行某些工作的服务器或不断执行的进程 处理数据?可能是我仍然误解新的关键词, 但这些类型的应用程序是否受益于新的关键字或 我们应该继续使用Tasks来实现更明确的多线程吗?
例如,我正在处理的应用程序(这是一个GUI应用程序,另外,也使用TAP来释放GUI线程)需要使用SSH与相当多的外部机器重复通信。想象一个大循环,其中应用程序需要a)向每个外部机器发送“命令”文件,b)不久之后,轮询所有外部机器的“进度”文件(即使用SSH尝试下载文件) ,c)不久之后,轮询所有这些机器的“完成”文件等;并且这些步骤一遍又一遍地重复,直到我们“完成”。
在这个应用程序的第一篇文章中,所有这些SSH i / o都是同步完成的,每个步骤的累计时间花了太长时间。更不用说它不能很好地扩展,因为我们要求应用程序支持更多的外部机器。
我已经重写了这个应用程序,同时执行上述每个步骤(a,b,c)。因此,例如,将命令文件发送到所有外部机器或多或少同时发生,而不是一个接一个地发生,允许应用程序在这些步骤(a,b,c)之间更快地移动随着我们添加更多外部机器,降级程度降低。
我通过Task.Run()启动每个ssh操作,因为我正在使用的SSH库本身不提供“异步”功能(但是库是线程安全的),然后我用'等待所有这些'等待Task.WhenAll(任务列表)'。完成后,我会检查每项任务以查看结果,然后相应地进行。
除了使用TAP在代码中查看所有这些都非常易于理解和令人愉快之外,我还使用它对取消和进度对象的支持来处理取消并向用户报告这些进度活动。
到目前为止,这种方法运作得非常好,而且我没有比这更深入地进入TPL等等。有些人提到当你“大量并发”时,你可能不得不深入研究TPL,但我还没有亲自见过“为什么”......
所以我想说,不要根据应用程序的“类型”(gui,服务器等)来确定TAP的用途,而是根据你需要在应用程序中执行的活动的性质来确定TAP的用途。如果你需要同时进行多个计算,TAP可能会很棒。如果你有很多需要同时完成的i / o,那么TAP可能很棒。我们都知道使用TAP释放GUI线程的典型示例。