定义异步函数

本节内容可参考示例文件"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外,所有的规范都不是强制的,但建议遵循这些规范,避免给后来者带来混淆。


本页地址:http://www.foxtable.com/webhelp/topics/6362.htm