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 предназначен для работы потока. Процедура должна иметь следующую сигнатуру (те же параметры, те же вызовы), совместимымую с procptr:
Declare Sub myThread ( ByVal userdata As Any Ptr )
userdata
Параметр Any Ptr - параметр Sub , предназначен для работы потока. FreeBASIC ожидает, что этот параметр должен присутствовать, он не должен быть опущен!
param
Any Ptr аргумент, который будет передаваться в потоке Sub , на который указывает procptr через свой параметр userdata. Например, это может быть указатель на структуру или массив, содержащий различную информацию для потока. Если param не используется, 0 (нуль) будет передан параметру для пользовательских данных в потоке.
stack_size
Дополнительное количество байтов зарезервированных для стека этого потока.

Возвращаемое значение

Threadcreate возвращает Any Ptr дескриптор созданного потока, или нулевой указатель (0) в случае неудачи.

Описание

Процедура, на которую указывает procptr запускается как поток. Ей будет передано содержание param, или 0 (нуль) если не указано, в ее параметр userdata.

Процедура, которая была запущена как поток, будет выполняться параллельно с основной частью программы. В операционной системе это достигается путем передачи выполнения ее другому процессору, если он существует, или чередуя выполнения потоков на одном процессоре. Нет гарантии о порядке, в котором различные потоки выполняются, и нет никаких предположений о порядке, в котором несколько создаваемых потоков фактически начинают выполнение.

Перед закрытием программы следует ждать окончания всех запущенных потоков с помощью ThreadWait. Кроме того, если в этом нет необходимости, можно спокойно дожидаться окончания выполнения потока с помощью Threaddetach . Однако, если программа выходит в то время как некоторые потоки все еще активны, эти потоки будут прерваны системой. Для каждого созданного потока, программа должна вызвать либо ThreadWait либо Threaddetach для того, чтобы системные ресурсы, связанные с дескрипторами потоков освобождались. В противном случае, могут быть утечки памяти или системных ресурсов.

Из-за характера потоков нельзя сделать никаких предположений о порядке выполнения. Для обмена данными между несколькими потоками, включая поток и основную частью программы, необходимо использовать мьютексы. Эти блокировки взаимного исключения могут «принадлежать» одному потоку при выполнении критической работы, заставляя другие потоки ожидать своей очереди. См. MutexCreate, MutexLock, MutexUnlock, MutexDestroy.

stack_size может использоваться для изменения размера стека потока от системного по умолчанию. Это может быть полезно, когда программа требует большой стек, например из-за многоуровневой рекурсии процедуры или при распределении огромных строк/массивов в стеке. На некоторых системах (Linux) стек автоматически правит stack_size , если требуется больше места; на других (Win32), это фиксируется как максимально допустимое. Поведение не определяется, когда используется больший размер стека, чем зарезервированный для системы, в которой стек не может быть увеличен.

Пример

'' Потоковая синхронизация с использованием мьютексов
'' Если вы закомментируйте строки, содержащие «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 создает ожидание одновременно запущенных потоков,
    '' так что только один за раз может продолжаться и выводить печать.
    '' В противном случае, потоки начнут вмешиваться в работу друг друга и портить,
    '' так как существует только один курсор.

    ''
    '' Невозможно предсказать порядок, в котором здесь выполняются потоки
    '' и какой из них будет первым для получения блокировки
    '' и заставляя остальных ждать.
    ''
    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 "Thread (" & 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 "Error creating thread:"; 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 " main thread: ."
    Print "other thread: *"

    '' Запускаем другой поток
    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 ", consumer gets:", i
        Sleep 500
        MutexUnlock consumed
    Next
End Sub

Sub producer( ByVal param As Any Ptr )
    For i As Integer = 0 To 9
        Print "Producer puts:", 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 "Error creating mutexes! Exiting..."
        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 "Error creating threads! Exiting..."
        End 1
    End If

    ThreadWait consumer_id
    ThreadWait producer_id

    MutexDestroy consumed
    MutexDestroy produced

    Sleep


Различия диалектов

  • Многопоточность не допускается в диалекте -lang qb.

Различия платформ

  • Threadcreate не доступна в версии DOS FreeBASIC, потому что многопоточность не поддерживается ядром DOS.
  • В Linux потоки всегда запускаются в том порядке, котором они были созданы , это нельзя предположить (угадать) в Win32. Это вопрос операционных систем, а не FreeBASIC

Отличия от QB

  • Новое в FreeBASIC

См. также