Основной код, который формирует логику работы приложения и в котором реализуются различные алгоритмы, пишется в процедурах или функциях. При запуске процедур/функций их код выполняется последовательно, при этом если в коде производится какое-либо длительное действие, то приложение будет ожидать его завершения, элементы управления форм буду недоступны. Для того чтобы была возможность продолжать работать в приложении, запуск длительных операций осуществляют в отдельных потоках. Потоки позволяют выполнять операции параллельно основному коду приложения, при этом из приложения можно отслеживать и управлять состоянием потока.
В языке 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(0, 100) > 50 Then
Value := Value + 1
Else
Value := Value - 1
End If;
End For;
ThName := (Th As IForeThread).Name;
//Выход из критической секции
CCritSection.CritSection.Leave;
End Sub Calculate;
См. также: