ThreadCreate
 
在单独的执行线程中启动用户定义的过程

语法

Declare Function ThreadCreate _
( _
ByVal procptr As Sub ( ByVal userdata As Any Ptr ), _
ByVal param As Any Ptr = 0, _
ByVal stack_size As Integer = 0 _
) As Any Ptr

用法

result = ThreadCreate ( procptr [, [ param ] [, stack_size ] ] )

参数

procptr
指向Sub的指针旨在作为线程工作。sub必须具有与procptr 兼容的以下签名(相同的参数,相同的调用约定):
Declare Sub myThread ( ByVal userdata As Any Ptr )
userdata
SubAny Ptr参数旨在作为线程工作。FreeBASIC希望这个参数存在,不能省略!
param
Any Ptr参数将通过userdata 参数传递给由procptr 指向的线程Sub.例如,这可以是一个指向一个结构或一个数组的指针,该数组包含用于线程子项的各种信息。如果没有给出param 0(零)将被传递给线程子的userdata 参数。
stack_size
为该线程的堆栈预留的可选字节数。

返回值

ThreadCreate在创建的线程上返回一个Any Ptr句柄,或者在失败时返回一个空指针(0)。

说明

procptr 指向的子句作为线程启动。在param 参数中,它将传递param 的内容,如果未指定,则会传递0(零)。

作为线程启动的子程序将与程序的主要部分并行执行。OS通过将其赋值给不同的处理器(如果存在)或通过在单个处理器上的执行线程之间交替来实现。不能保证不同线程执行的顺序,也不能对多个创建线程实际开始执行的顺序做出假设。

关闭之前,程序应等待所有启动的线程的终止使用ThreadWait.或者,如果没有必要安全地等待线程完成执行,则可以使用Threaddetach.但是,如果程序在某些线程仍然处于活动状态时退出,那么这些线程将被系统中止。对于创建的每个线程,程序应调用ThreadWaitThreaddetach以确保释放与线程句柄相关联的系统资源。否则可能会有内存或系统资源泄漏。

由于线程的性质,不能对执行顺序进行任何假设。为了在多个线程之间交换数据,包括线程和程序的主要部分,必须使用互斥体。这些互斥锁可以在执行关键工作时由单个线程“拥有”,从而导致其他线程轮流等待。请参阅MutexCreateMutexLockMutexUnlockMutexDestroy.

可以使用stack_size 从系统的默认值更改线程的堆栈大小。当程序需要大的堆栈时,例如由于大量的过程递归或者在堆栈上赋值大量的字符串/数组时,这可能很有用。在某些系统(Linux)上,如果需要更多空间,则堆栈自动增长超过stack_size 在其他(Win32)上,这是允许的固定最大值。当堆栈不能生长的系统上使用的堆栈数量大于预留大小时,行为是未定义的。

例子

''使用Mutexes进行线程同步
''如果您注释掉包含“MutexLock”和“MutexUnlock”的行,
''线程将不会同步,并且可能会打印一些数据
''空间不足。

Const MAX_THREADS = 10

Dim Shared As Any Ptr ttylock

''电报在给定位置的屏幕上展开一些文字
Sub teletype( ByRef text As String, ByVal x As Integer, ByVal y As Integer )
    ''
    ''这个MutexLock使同时运行的线程等待每个
    ''其他,所以一次只能一个可以继续打印输出。
    ''否则,他们的定位将会干扰,因为只有一个
    ''光标。
    ''
    '' It'不可能预测线程到达的顺序
    ''在这里,哪一个将是第一个获得锁的
    ''导致其余的等待。
    ''
    MutexLock ttylock

    For i As Integer = 0 To (Len(text) - 1)
        Locate x, y + i
        Print Chr(text[i])
        Sleep 25
    Next

    ''MutexUnlock释放锁并让其他线程获取它。
    MutexUnlock ttylock
End Sub

Sub thread( ByVal userdata As Any Ptr )
    Dim As Integer id = CInt(userdata)
    teletype "线程(" & id & ").........", 1 + id, 1
End Sub

    ''创建一个互斥体来同步线程
    ttylock = MutexCreate()

    ''创建子线程
    Dim As Any Ptr handles(0 To MAX_THREADS-1)
    For i As Integer = 0 To MAX_THREADS-1
        handles(i) = ThreadCreate(@thread, CPtr(Any Ptr, i))
        If handles(i) = 0 Then
            Print "创建线程时出错:"; i
            Exit For
        End If
    Next

    ''这是主线程。现在等待所有的子线程完成。
    For i As Integer = 0 To MAX_THREADS-1
        If handles(i) <> 0 Then
            ThreadWait(handles(i))
        End If
    Next

    ''完成后清理
    MutexDestroy(ttylock)


Sub print_dots(ByRef char As String)
    For i As Integer = 0 To 29
        Print char;
        Sleep CInt(Rnd() * 100), 1
    Next
End Sub

Sub mythread(param As Any Ptr)
    ''工作(其他线程)
    print_dots("*")
End Sub

    Randomize(Timer())

    Print "主线程:"
    Print "其他线程:*"

    ''启动另一个线程
    Dim As Any Ptr thread = ThreadCreate(@mythread, 0)

    ''工作(主线程)
    print_dots(".")

    ''如果需要,等待其他线程完成
    ThreadWait(thread)
    Print
    Sleep


''使用互斥体的线程消费者/制作者示例

Dim Shared As Any Ptr produced, consumed 

Sub consumer( ByVal param As Any Ptr )
    For i As Integer = 0 To 9
        MutexLock produced
        Print "消费者得到:", i
        Sleep 500
        MutexUnlock consumed
    Next
End Sub

Sub producer( ByVal param As Any Ptr )
    For i As Integer = 0 To 9
        Print "制片人:", i;
        Sleep 500
        MutexUnlock produced
        MutexLock consumed
    Next i
End Sub

    Dim As Any Ptr consumer_id, producer_id

    produced = MutexCreate
    consumed = MutexCreate
    If( ( produced = 0 ) Or ( consumed = 0 ) ) Then
        Print "创建互斥体时出错!退出..."
        End 1
    End If

    MutexLock produced
    MutexLock consumed
    consumer_id = ThreadCreate(@consumer)
    producer_id = ThreadCreate(@producer)
    If( ( producer_id = 0 ) Or ( consumer_id = 0 ) ) Then
        Print "创建线程时出错!退出..."
        End 1
    End If

    ThreadWait consumer_id
    ThreadWait producer_id

    MutexDestroy consumed
    MutexDestroy produced

    Sleep


方言差异

  • -lang qb 方言中不允许使用线程。

平台差异

  • Threadcreate不适用于FreeBASIC的DOS版本/目标,因为DOS内核和所使用的扩展程序不支持多线程。
  • 在Linux中,线程始终按照创建的顺序启动,这在Win32中是不可以假定的。这是一个操作系统,而不是FreeBASIC的问题。

与QB差别

  • 新的FreeBASIC

参考