同步函数示例

本节我们介绍同步函数,同步函数通常用于集中处理异步函数的运行结果。

上一节我们提出了一个问题,用异步函数进行累加,会因为冲突产生错误的结果。

那么如何得到正确的结果呢?

我们可以定义一个函数,这个函数同时只能有一个线程调用,如果有多个线程同时调用此函数,那么就必须排队,上一个线程调用完毕后,下一个线程才会继续,我们称这类函数称为同步函数。

有了同步函数,这样可以开启多个线程执行分别进行计算,然后将结果传递给此同步函数,统一进行处理,以避免上一节提到的冲突问题。

同步函数使用示例

1、定义Public变量

首先我们在全局代码中定义一个Public变量:

Public Total As Integer

2、定义同步函数

定义一个名为AddTotal的函数,其代码为:

Total = Total + Args(0)

这个函数将在异步函数中被同步调用,用于累加各异步函数产生的结果。

3、定义异步函数

然后定义一个名为AddSubtotal的函数,这个函数将在主线程中被异步调用,其代码为:

Dim Sum As Integer
For
i As Integer = 1 To 100
   
Sum = Sum + 1
Next

Functions
.BeginSyncExecute("AddTotal",Sum) '调用同步函数AddTotal累加结果

4、测试结果

然后在命令窗口执行代码:

Total = 0
For
i As Integer = 1 To 100
   
Functions.AsyncExecute("AddSubtotal")
Next


在命令窗口删除以上代码,然后执行:
Return Total

现在你反复测试,会发现Total的值始终都等于10000。

5、执行过程与原理

主线程用AsyncExecute方法异步执行AddSubtotal函数100次,等于开启了100个子线程同时执行AddSubtotal方法,各子线程中的AddSubtotal方法完成数字累加后,用BeginSyncExecute方法同步执行函数AddTotal,将结果累加到全局变量Total,因为即使有多个子线程同时用BeginSyncExecute方法调用AddTotal,也只会有一个线程调用成功,其余需要排队等候执行,所以不会再有冲突发生。

6、慎用Sleep方法!

认真学习的用户可能已经想到了,这里为啥要两次执行? 直接在主线程用Sleep方法等2秒,待子线程执行完毕显示Total的值即可啊:

Total = 0
For
i As Integer = 1 To 100
    Functions.AsyncExecute("
AddSubtotal")
Next

Sleep
(2000)
Return
Total

结果出乎意料,Total的值为0,为什么呢?

因为同步函数是在主线程中执行的,而上述代码暂停主线程2秒,所有子线程通过BeginSyncExecute调用AddTotal方法时,也都需要排队等候两秒才执行,所以2秒后主线程获取Total值时,可能还没有一个子线程将结果累加到Total变量,所以Total的结果为0。

同样的原因,我们不应该在同步函数中用Sleep方法,这会导致主线程和其他所有同步函数处于等待状态,总之除非用于测试,否则:

不要在主线程用Sleep!

不要在同步函数用Sleep!


自动等待异步函数执行完毕

作为一个面向非专业人士的开发平台,Foxtable并未提供等待异步函数执行完毕的功能,实际开发过程中也少有此种需要发生。
如果你确实需要在全部异步函数执行完毕后,自动执行特定的代码,可以参考下面的代码。
继续以前面的异步累加为例:

1、定义Public变量

首先我们在全局代码中定义一个Public变量:

Public Total As Integer
Public
TCount As Integer

我们在这里增加了一个计数器变量TCount。

2、定义同步函数

定义一个名为AddTotal的函数,其代码为:

Total = Total + Args(0)
TCount
  = TCount - 1
If
Tcount = 0 Then
    MessageBox.Show("计算完成,结果为:" & Total)

End
If

这个函数将在异步函数中被同步调用,用于累加各异步函数产生的结果。

3、定义异步函数

然后定义一个名为AddSubtotal的函数,这个函数将在主线程中被异步调用,其代码为:

Dim Sum As Integer
For
i As Integer = 1 To 100
   
Sum = Sum + 1
Next

Functions
.BeginSyncExecute("AddTotal",Sum) '调用同步函数AddTotal累加结果

4、测试结果

然后在命令窗口执行代码:

Total = 0
TCount
= 100
For
i As Integer = 1 To TCount
   
Functions.AsyncExecute("AddSubtotal")
Next

原理很简单,TCount变量的初始值为100,表示异步函数要调用100次,每次异步函数(AddSubtotal)执行完毕后,都会调用同步函数(AddTotal),此函数每执行一次,就将TCount减1,当TCount的值等于0,表示所有的100个异步函数都执行完毕了。


本页地址:http://www.foxtable.com/mobilehelp/topics/3270.htm