c# 并行执行两个异步方法_如何使用DispatchGroup执行并行异步操作

c# 并行执行两个异步方法

并发 (Concurrency)

Have you ever wanted to call multiple API endpoints at the same time and be notified when all have finished? Maybe you want to batch asynchronous operations and know when the all of the operations in the batch have finished.

您是否曾经想过同时调用多个API端点,并在所有端点完成后收到通知? 也许您想批处理异步操作,并知道批处理中的所有操作何时完成。

There are many reasons you might want to do multiple asyncronous operations in parrallel. In this tutorial we’ll be looking at performing in parallel multiple URL requests as a single operation.

您可能有很多原因想要并行执行多个异步操作。 在本教程中,我们将以单个操作的形式并行执行多个URL请求。

In this post we’ll learn how to use DispatchGroup to be notified when multiple concurrent asynchronous operations have finished. I assume you are familiar with the basics of Swift and Grand Central Dispatch.

在本文中,我们将学习如何使用DispatchGroup在多个并发异步操作完成时得到通知。 我认为您熟悉Swift和Grand Central Dispatch的基础知识。

I have used Swift 5.2.4 and Xcode 11.5 for this post.

我在这篇文章中使用了Swift 5.2.4和Xcode 11.5。

设置上下文 (Setting the context)

Let’s say you have a point of sale (POS) app. In this app the user is able to create a product to sell in the store. The user can also provide a CSV file with the products to create.

假设您有一个销售点(POS)应用程序。 在此应用程序中,用户可以创建要在商店中销售的产品。 用户还可以提供带有要创建的产品的CSV文件。

When the user creates a product through the app interface the app calls the POS backend API endpoint POST /product to create a single product.

当用户通过应用程序界面创建产品时,应用程序将调用POS后端API端点POST /product来创建单个产品。

Image for post

However when the user decides to create multiple products we need to call the endpoint for each product listed in the CSV file.

但是,当用户决定创建多个产品时,我们需要为CSV文件中列出的每个产品调用终结点。

Image for post

So how can we easily call the POST /product endpoint for each product on the CSV and get notified on completion of them all? The answer is using DispatchGroup!

那么,我们如何轻松地为CSV上的每个产品调用POST /product端点,并在完成所有操作时得到通知? 答案是使用DispatchGroup

Dispatch group allows you to group multiple asynchronous operations and be notified when all of them have completed.

调度组使您可以对多个异步操作进行分组,并在所有异步操作完成时得到通知。

如何使用调度组执行并行API请求 (How to perform parallel API requests using Dispatch Group)

In this section we’ll implement the parallel API request feature in the already existing POS app. The POS app and server will be provided.

在本节中,我们将在现有的POS应用程序中实现并行API请求功能。 将提供POS应用程序和服务器。

Here is the outline for this section:

这是本节的概述:

  1. Retrieve starter project

    检索启动项目
  2. Run server

    运行服务器
  3. Perform parallel API requests

    执行并行API请求
  4. Use DispatchGroup to get notified upon API requests completion

    使用DispatchGroup在API请求完成时获得通知

1.检索启动项目 (1. Retrieve starter project)

Let’s start by downloading the starter pack. Open terminal and execute the following commands:

让我们从下载入门包开始。 打开终端并执行以下命令:

cd $HOME
curl https://github.com/anuragajwani/dispatch-group-demo/archive/starter.zip -o dispatch_group_demo.zip -L -s
unzip -q dispatch_group_demo.zip

2.运行服务器 (2. Run server)

The starter project contains a server to run that will become the API which our app will communicate with and request to when creating products.

入门项目包含一个要运行的服务器,它将成为我们的应用在创建产品时与之通信并向其请求的API。

To run the server execute the following commands:

要运行服务器,请执行以下命令:

cd ~/dispatch-group-demo-starter/POSBackEnd
swift build
./.build/debug/POSBackEnd

When running the commands for the first time it can take a while to run the server. The first time the command will fetch the dependencies required to run the server.

首次运行命令时,可能需要一段时间才能运行服务器。 该命令第一次获取运行服务器所需的依赖项。

Image for post

For this project I have attached a Swift server that will act as out Products API. As it will run in our respective machines we will be easily be able to communicate with it using a simulator. However please note this won’t easily work with iOS devices.

对于这个项目,我已附加了一个Swift服务器,它将充当Products API。 由于它将在我们各自的机器上运行,因此我们将能够轻松地使用模拟器与之通信。 但是请注意,这不适用于iOS设备。

Also note that closing this terminal window will terminate the running server. Make sure the server is running at all times during this post.

另请注意,关闭此终端窗口将终止正在运行的服务器。 在此期间,请确保服务器始终在运行。

3.执行并行API请求 (3. Perform parallel API requests)

The starter project also contains an iOS app. The app is already capable of creating a single product.

入门项目还包含一个iOS应用程序。 该应用程序已经能够创建一个产品。

In this section we’ll fill out uploadProductsCSV and add the code to create multiple products in parallel.

在本部分中,我们将填写uploadProductsCSV并添加代码以并行创建多个产品。

First let’s open the app project. In a new terminal window execute the following command:

首先,让我们打开应用程序项目。 在新的终端窗口中,执行以下命令:

open -a Xcode ~/dispatch-group-demo-starter/POSDispatchGroupDemo/POSDispatchGroupDemo.xcodeproj

Next we’ll read file containing products in a CSV format. The file is included in the app. We’ll read the products.csv file and convert the products from CSV into Product on the function executed when the user taps Create products from products.csv button; theuploadProductsCSV function in ViewController.swift. I have already included a convenience function named getProductsFromCSV to do so. Thus we only need to call the function and store the products into a new variable.

接下来,我们将读取包含CSV格式产品的文件。 该文件包含在应用程序中。 当用户点击“ Create products from products.csv按钮时执行的功能上,我们将读取products.csv文件并将产品从CSV转换为ProductViewController.swiftuploadProductsCSV函数。 我已经包含了一个名为getProductsFromCSV的便捷函数。 因此,我们只需要调用函数并将产品存储到新变量中即可。

Open ViewController.swift and add the following line of code to uploadProductsCSV:

打开ViewController.swift并将以下代码行添加到uploadProductsCSV

let products = self.getProductsFromCSV()

Next we’ll take each product within the products and create POST /product request. I have already created a convenience function that does the request. We will only be required to call it. Add the following lines of code:

接下来,我们将采用产品中的每个products并创建POST /product请求。 我已经创建了一个方便的功能来执行请求。 我们只需要调用它。 添加以下代码行:

products.forEach({ product in
self
.createProduct(product, onCompletion: { _ in
// TODO handle completed product creation
})
})

Note for this post we are ignoring any request errors. The CSV contains valid products and the server is running locally so there shouldn’t be any error when communicating with the server.

请注意,此帖子我们将忽略任何请求错误。 CSV包含有效产品,并且服务器在本地运行,因此与服务器通信时不应有任何错误。

You should be able to run the app and create all the products on the products.csv. However we don’t have any mechanism yet to notify us when all the API requests have completed.

您应该能够运行该应用程序并在products.csv上创建所有产品。 但是,在所有API请求完成后,我们还没有任何机制可以通知我们。

4.使用DispatchGroup在API请求完成时获得通知 (4. Use DispatchGroup to get notified upon API requests completion)

Next we’ll use DispatchGroup to get notified when all API requests have completed.

接下来,我们将使用DispatchGroup在所有API请求完成后获得通知。

First let’s create an instance of DispatchGroup at the beginning of the function. Add the following line of code:

首先,让我们在函数开始处创建DispatchGroup的实例。 添加以下代码行:

let dispatchGroup = DispatchGroup()

Next before each createProduct call we need to add add dispatchGroup.enter(). On each completion of createProduct we must call dispatchGroup.leave(). The uploadProductsCSV function should look like:

接下来,在每个createProduct调用之前,我们需要添加add dispatchGroup.enter() 。 在createProduct每次完成时,我们都必须调用dispatchGroup.leave()uploadProductsCSV函数应如下所示:

@IBAction func uploadProductsCSV(_ sender: Any) {
let dispatchGroup = DispatchGroup()
let products = self.getProductsFromCSV()
products.forEach({ product in
dispatchGroup.enter()
self.createProduct(product, onCompletion: { _ in
dispatchGroup.leave()
})
})
}

dispatchGroup.enter() notifies the dispatch group that a new asynchronous call is made. dispatchGroup.leave() notifies the dispatch group that an asynchronous call has completed.

dispatchGroup.enter()通知调度组已进行新的异步调用。 dispatchGroup.leave()通知调度组异步调用已完成。

Next we’ll register a closure with the dispatch group that will be executed when all asynchronous operations have completed. At the end of uploadProductsCSV add the following line of code:

接下来,我们将在调度组中注册一个闭包,当所有异步操作完成时将执行该闭包。 在uploadProductsCSV的末尾添加以下代码行:

dispatchGroup.notify(queue: .main, execute: { self.showProductsCreatedAlert() })

It is important that notify is called after we tell dispatch group about all the asynchronous calls are made. If we register the closure before we notify the dispatch group about the asynchronous calls to be made then the closure will be called immediately. Why? Dispatch group calls the closure when the counter of currently executing asynchronous calls reaches 0. If we register the closure before we tell dispatch group about the asynchronous calls made the counter will effectively be at 0 and the dispatch group will execute the notify closure.

重要的是, 我们通知调度组所有异步调用完成之后 ,调用notify 。 如果在通知派发组有关异步调用之前注册了闭包,那么将立即调用闭包。 为什么? 当当前正在执行的异步调用的计数器达到0时,调度组将调用闭包。如果在向调度组通知异步调用之前注册闭包,则计数器实际上将为0,而调度组将执行通知闭包。

For each product sent to the server the counter will increase by 1 (when we call dispatchGroup.enter()). The counter will decrease by 1 when we finish sending a product (when we call dispatchGroup.leave()). When the counter reaches 0 the dispatch group will execute the closure registered (the one we provide to dispatchGroup.notify(queue:_, execute:_)).

对于发送到服务器的每个产品,计数器将增加1(当我们调用dispatchGroup.enter() )。 当我们完成发送产品时(当我们调用dispatchGroup.leave() ),计数器将减少1。 当计数器达到0时,调度组将执行已注册的闭包(我们提供给dispatchGroup.notify(queue:_, execute:_)的闭包)。

And that’s it! Run the POSDispatchGroupDemo app on a simulator and tap on the Create products from products.csv button and see it in action!

就是这样! 在模拟器上运行POSDispatchGroupDemo应用程序,然后点击“ Create products from products.csv按钮,然后查看运行情况!

Image for post

There are 5 products in the CSV file. Those are the iPhones on sale at the time of writing on the Apple website and their UK prices. You can see the products being created on the terminal window running the server.

CSV文件中有5个产品。 这些是在Apple网站上撰写本文时正在销售的iPhone及其在英国的价格。 您可以在运行服务器的终端窗口上看到正在创建的产品。

摘要 (Summary)

In this post we have learnt to perform parallel asynchronous and get notified upon completion of all asynchronous operations.

在本文中,我们学习了执行并行异步,并在所有异步操作完成后得到通知。

You can find the full source code in the repo below:

您可以在下面的仓库中找到完整的源代码:

最后说明 (Final Notes)

DispatchGroup is a great simple tool to use when you want to quickly batch multiple asynchronous operations. However currently DispatchGroup doesn’t offer any mechanism out of the box to notify us when one operation has completed and how many are left.

当您要快速批处理多个异步操作时,DispatchGroup是一个非常简单的工具。 但是,当前DispatchGroup尚不提供任何开箱即用的机制来通知我们何时完成一个操作以及还有多少操作。

There are also many other ways of grouping asynchronous operation and getting notified upon the completion of each individual operation as well the whole. One example of such solution is using reactive programming framework.

还有许多其他方式可以将异步操作分组并在每个单独操作以及整个操作完成时得到通知。 这种解决方案的一个示例是使用React式编程框架

Stay tuned for more posts on iOS development! Follow me on Twitter or Medium!

请继续关注有关iOS开发的更多帖子! 在TwitterMedium上关注我!

翻译自: https://medium.com/@anuragajwani/how-to-perform-parallel-asynchronous-operations-with-dispatchgroup-3c112deda62c

c# 并行执行两个异步方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值