多任务
青语言中多任务类似于其他语言中的多线程、并行的概念,因为底层通过C#的Task实现,所以我们称其为——多任务。
通常情况下我们写的程序会运行在一个线程中,而当前主流的CPU通常有多个核心,以更好地支持真正的多线程并行。CPU单核的性能是有限的,当我们发现我们的程序存在性能瓶颈,但可以拆分为互相独立的数个任务并行执行时,就可以考虑使用多线程执行。
青语言中我们不直接操作线程,我们只需要设定一个任务,然后交给解释器去执行就行了,这样的执行方式就是多任务执行。
下面我们来看青语言中多任务执行的实现方式:
分支
如果我们需要开启1个新的任务,那么可以使用内置的原生函数@分支
@原生函数-分支{参数1-代码块,返回任务;开启新的任务,执行参数1代码块中的代码}
这个函数非常简单只需要传入1个代码块即可
@分支、元{
@延时任务【3000,元{@显示、“你好”}】
}

这里我们同样开启了一个延时任务,但是注意,这个延时任务并不是在当前我们程序运行的中任务中执行的,而是在一个新的任务中执行的。
按下回车后,我们看到@分支函数本身返回的是一个异步任务……。
这不是我们之前学习过的青语言中的基本数据类型,而是内置的特定用于实现多任务的数据类型,用来表示新开启的这个任务。
等待任务
有时我们需要明确任务之间的先后顺序,我们开启了一个新的任务,然后我们希望先等待新的任务执行完之后,再接着执行当前任务,那么我们可以使用关键字等待来实现
#新任务 = @分支、元{
@显示、“你好”
}
#结果 = 等待 #新任务
只要等待关键字后面跟着的一个值是任务类型,就会等待这个任务执行完毕,然后返回这个任务执行代码块的结果
另外我们也可以使用函数的方式等待任务,内置原生函数@等待任务
参数1-任务,可选参数2-整数,返回任意;等待一个异步任务,如果传入参数2可指定最大等待时长(默认无限等待),等待结束后如果未超时返回任务结果,否则返回任务本身
示例:
@等待任务、#新任务
@等待任务【#新任务, 5000】 ;我们可以设置等待的最大时长,这里是5秒
并行
如果我们需要一次开启多个新的任务,那么可以使用内置的原生函数@并行
@原生函数-并行{参数1-数组,可选参数2-逻辑,可选参数3-整数,返回任务数组;一次性开启多个任务,参数1是代码块数组,参数2表示是否等待所有任务结束(默认不等待),参数3设置等待的超时时间(毫秒)}
基础用法:
#任务数组 = @并行【
【
元{@显示、“你好”},
元{@显示、“你好”},
元{@显示、“你好”},
】
】
我们传入了一个包含3个代码块的数组,那么就会开启3个任务,返回包含3个任务的数组。
我们开启多个任务之后,可以选择是否等待这些任务全部执行完毕,也可以执行最长的等待时间。
#任务数组 = @并行【
【
元{@显示、“你好”},
元{@显示、“你好”},
元{@显示、“你好”},
】,
真,
5000
】
这里我们传入第2个参数为真,表示开启这些任务后,等待这些任务全部执行完毕。第3个参数是最长等待时间的毫秒数,这里表示最长等待5秒,如果五秒后这3个任务还没执行完毕,那么就不再等待了。
多任务可以通过并行执行提升程序的运行效率,然而多任务并不是绝对好的。事实上多任务并行会导致程序的执行次序比较复杂,容易造成程序出错,且多任务下,对异常的处理会变得比较困难。因此,通常情况下,如果没有对运行效率的迫切需求,请尽量不要使用多任务。
多任务下容易出现的一种问题是数据竞争的问题,也就是当多个任务同时对1个数据进行操作时,容易出现错误。此时我们需要保证同一时间内只有一个任务可以访问某个数据,可以通过锁的方式来实现。
@并行锁【#变量,元{
#变量 加等 1
}】
这段代码里,当前任务执行这个函数时,会对参数一加上1个锁,然后去执行参数二的代码块,执行结束后再释放锁。
如果其他任务这个时候去访问#变量,就会发现上了锁,那么就会等待,直到锁被释放。
这样我们就可以保证这个#变量同一时间只会被1个任务访问到。