Работа с потоками

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

В языке Fore потоки реализует класс ForeThread. Поток создаётся на базе пользовательского метода, реализуемого классом ForeMethod. Пользовательский метод должен быть связан с процедурой/функций, находящейся в глобальном пространстве имён сборки:

Sub StartThread;
Var
    Method: IForeMethod;
    Th: IForeThread;
Begin
    Method := 
New ForeMethod.Create;
    Method.Assembly := 
"M_Thread";
    Method.Method := 
"Calculate";
    Th := 
New ForeThread.Create(Method);
    Th.Start(Th);
End Sub StartThread;

Sub Calculate(Param: Variant);
Var
    Th: IForeThread;
    i: Integer;
Begin
    Th := Param 
As IForeThread;
    
For i := 1 To 100 Do
        
//...
        Debug.WriteLine("Working thread..." + i.ToString);
        Th.Sleep(
100);
        
//...
    End For;
End Sub Calculate;

Взаимодействие с потоками может осуществляться через глобальные переменные, статические поля или свойства классов. Чтобы не возникло конфликтов, когда различные потоки одновременно пытаются изменить значение какого-либо одного общего ресурса, используются критические секции. Критическую секцию реализует класс ForeCriticalSection. Доступ к общим ресурсам должен осуществляться между вызовами методов Enter и Leave:

Var Value: Integer;

Class CCritSection: Object
    
Shared fcs: IForeCriticalSection;
    
Public Shared Property CritSection: IForeCriticalSection
        
Get
        
Begin
            
If IsNull(fcs) Then
                fcs := 
New ForeCriticalSection.Create;
            
End If;
            
Return fcs;
        
End Get
    
End Property CritSection;
End Class CCritSection;

Sub StartThread;
Var
    Method: IForeMethod;
    Th1, Th2: IForeThread;
Begin
    Method := 
New ForeMethod.Create;
    Method.Assembly := 
"M_Thread";
    Method.Method := 
"Calculate";
    
//Создание потоков
    Th1 := New ForeThread.Create(Method);
    Th1.Name := 
"A";
    Th1.Start(Th1);
    Th2 := 
New ForeThread.Create(Method);
    Th2.Name := 
"B";
    Th2.Start(Th2);
End Sub StartThread;

Sub Calculate(Th: Variant);
Var
    i: Integer;
Begin
    
//Вход в критическую секцию
    CCritSection.CritSection.Enter;
    
For i := 0 To 100 Do
        
If Math.RandBetweenI(0100) > 50 Then
            Value := Value + 
1
        
Else
            Value := Value - 
1
        
End If;
    
End For;
    ThName := (Th 
As IForeThread).Name;
    
//Выход из критической секции
    CCritSection.CritSection.Leave;
End Sub Calculate;

См. также:

Разработка прикладного приложения