定义异步函数
本节内容可参考示例文件"CaseStudy\异步函数.Table"。
通过上一节,我们已经知道:
1、在Foxtable中,同一个自定义函数,你用Execute方法执行,它就是同步函数,你用ExecuteAsync执行,它就是异步函数。
2、通过ExecuteAsync方法异步执行函数时,如果要获取函数返回的结果,或者需要等函数执行完毕才运行后续代码,那么需要加上Await关键词。
3、如果代码中用到了Await关键词,那么第一行必须是注释标记:'''Async
那是不是说Foxtable就不存在同步函数和异步函数之分呢?
当然不是,Foxtable只是提供了异步执行普通函数的方法,让一个普通函数可以表现得和异步函数一样。
对于需要异步执行的函数,我们强烈建议你将其定义为异步函数,而不是定义为普通函数。
那么什么是异步函数呢?很简单:
异步函数就是第一行加上了注释标记'''Async,且函数名以Async结尾的函数。
示例
增加一个新的自定义函数TotalAsync,代码为:
'''Async
Dim
result
As
Long
'函数本身的代码
Dim
sum
As
Long
=
Await
Functions.ExecuteAsync("SumAsync")
'执行异步函数
Dim
max
As
Long
= Functions.Execute("Max",
100, 200, 300)
'执行同步函数
For
i
As
Integer
= 1
To
10
result =
result + 5
Next
result = result + max + sum
Return
result
这个函数第一行为注释标记'''Async,所以是一个异步函数。
现在可以在命令窗口测试这个函数:
'''Async
Dim
result
As
Long
=
Await
Functions.ExecuteAsync("TotalAsync")
Return
result
等待一段时间后,会出现计算结果,在等待期间你可以继续进行其他操作。
看起来和以前一样,没有什么区别啊?
有不同的,异步函数无法常规执行,在命令窗口执行下面的代码:
Dim
result
As
Long
= Functions.Execute("TotalAsync")
'会出错
Return
result
将会提示错误。
同步执行异步函数
前面提到,异步函数强制你用ExecuteAsync方法执行,例如:
Dim
result
As
Long
= Functions.Execute("TotalAsync")
'会出错
Return
result
当这个强制是要打双引号的,我们依然有办法同步执行异步函数,将代码改为:
'''Async
Dim
result
As
Long
=
Await
Functions.Execute("TotalAsync")
'不出错了
Return
result
等待一段时间后,会出现计算结果,在等待期间不会卡死界面,你可以继续进行其他操作。
那么看起来和用ExecuteAsync执行一样的啊,而且这里分明是同步执行,为什么函数执行过程中表现出异步特征(不会卡死界面)呢?
这是因为,虽然TotalAsync函数是同步执行的(使用Execute),但TotalAsync函数内部的代码包含了异步操作,具体来说,当程序执行到下面这一行时:
Dim
sum
As
Long
=
Await
Functions.ExecuteAsync("SumAsync")
'执行异步函数
TotalAsync会释放控制权,等到SumAsync函数运行结束才恢复控制权,在这个等待的过程中,你可以进行其他操作,使得TotalAsync函数看起来是在异步执行。
所以对于异步函数,即使用Execute方法同步执行,可能也会表现出一些异步执行的特征,至于异步特征的有无和多少,取决
于是否用了ExecuteAsync执行异步函数,以及这个异步函数的执行时间,如果这个异步函数能瞬间执行完毕,你大概率不会有任何感觉。
对于异步函数,用Execute方法同步执行和用ExecuteAsync执行的区别在于:
1、函数中用ExecuteAsync执行的代码,始终都是异步执行的。
2、函数中其他的代码是异步执行还是同步执行,取决于你用Execute还是ExecuteAsync方法执行函数,用前者就是同步执行,用后者就是异步执行。
现在增加一个新的异步函数Total2Async,代码为:
'''Async
Dim
max
As
Long =
Await
Functions.ExecuteAsync("Max",
100, 200, 800)
'执行异步函数,瞬间完成
'尽管是异步函数,但如果用Execute执行,函数本身代码将会同步执行的,这个循环会耗费大量的时间,所以程序会失去响应
Dim
sum
As
Long
For
m
As
Integer
= 1
To
10000
For
i
As
Integer
= 0
To
1000000
sum =
sum + i
Next
Next
Return
sum + max
现在在命令窗口执行:
'''Async
Dim
result
As
Long
=
Await
Functions.Execute("Total2Async")
Return
result
程序会失去响应,界面被卡死,原因我已经在Total2Async的注释中说明了。
如果修改代码为:
'''Async
Dim
result
As
Long
=
Await
Functions.ExecuteAsync("Total2Async")
Return
result
现在就是一个彻底的异步函数,在等待期间不会卡死界面,你可以继续进行其他操作。
总结:
在Foxtable中,异步函数和同步函数的区分是模糊的,异步函数可以用Execute同步执行,同步函数可以用ExecuteAsync异步执行,而注释标记'''Async只是用于决定函数代码中是否可以使用Await关键词。
实际开发的时候,我们要遵循一些规范,以免给后来者带来混淆:
1、对于异步函数,函数名统一用Async结尾,且在第一行加上注释标记:'''Async,执行的时候用ExecuteAsync方法执行
2、对于普通函数,函数名不可以用Async结尾,执行的时候用Execute方法执行。
3、对于普通函数,如果要用Await执行异步函数(包括第三方的),可在第一行加上注释标记:'''Async
除了要用Await的时候第一行必须加上注释标记'''Async外,所有的规范都不是强制的,但建议遵循这些规范,避免给后来者带来混淆。