Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Потоки (Thread)


Страницы:   1 2 3

sdw_syscoder ©   (2004-08-02 01:24:00) 

Задача откровенно говоря несложная. Вообщем есть два потока. Сначала запускаем FirstThread, затем после его завершения нужно запустить SecondThread (описания этих классов находятся в разных юнитах). Как это сделать практически?


Digitman   (2004-08-02 14:39:00) [21]

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

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


Sha   (2004-08-02 14:35:00) [22]

а кто такой Thread как узнал?


sdw_syscoder   (2004-08-02 14:24:00) [23]

Для начала объясни мне кто  это такой -  PostMessage.


Sha   (2004-08-02 14:20:00) [24]

sdw_syscoder   (02.08.04 14:16) [19]

Ну и шли данные между потоками через PostMessage(...


sdw_syscoder   (2004-08-02 14:16:00) [25]

> panov ©   (02.08.04 13:01) [18]

Да, всё верно.


panov   (2004-08-02 13:01:00) [26]

Зря ты так расписывал.

Как я понял твою задачу:
1. Поток непрерывно получает данные(неважно откуда) и формирует буфер принятых данных.
2. После заполнения буфера эти данные должны передаться в другой поток для обработки, првый поток в это время продолжает читать.
3. После обработки данных вторым потоком в основном кодовом потоке должно произойти отображение информации.

Я правильно описал задачу?


Digitman   (2004-08-02 12:59:00) [27]


> В процедуре DoRead происходит запись в массив


1. Для чего перемалывать из пустого в порожнее, переписывая буфер приема в массив ?

2. Для чего синхронизировать ВСЮ процедуру DoRead с осн.трэдом, если в ней нет опасных обращений к VCL-контролам ?


sdw_syscoder   (2004-08-02 12:21:00) [28]

СХЕМА ТАКАЯ:

1. Есть отдельный юнит, а в нём класс TReadThread = class(TThread), в котором происходит инициализация связи с внешним устройством и непосредственно чтение в цикле средствами синхронизации.


procedure TReadThread.Execute;
 while not Terminated do
 ...
 ReadFile(FComPort.FPort, FBuf, FactBytes, FactBytes, @FOverRead);
 Synchronize(DoRead);
 ...
 end;
end;


2. В процедуре DoRead происходит запись в массив

// procedure DoRead описана в разделе private потока
procedure TReadThread.DoRead;
var
 arrBytes: array of Byte;
 i: Integer;
begin
 if Assigned(FComPort.FReadEvent) then
 begin
   SetLength(arrBytes, FactBytes);
   for i := Low(FBuf) to FactBytes - 1 do
     arrBytes[i] := FBuf[i];
   FComPort.FReadEvent(Self, arrBytes);
   arrBytes := nil;
  end;
end;


3. И одновременно в главном юните считывание из массива в DataArray: string.


// OnRead - свойство класса TComPort
procedure TReceiveForm.OnRead(Sender: TObject; ReadBytes: array of Byte);
var
   I: integer;
begin
 for i := Low(ReadBytes) to High(ReadBytes) do DataArray := DataArray + IntToHex(ReadBytes[i], 2);
end;


4. После как всё прочитано, из потока FReadThread мы запускаем второй поток, где и происходит обработка DataArray.
До этого у меня просто через синхронизатор вызывалась процедура обработки строки DataArray. Думал поток поможет, а оказалось - нет.

5. Ну, а преобразование данных выложено в постере [8].

В принципе всё.


sdw_syscoder   (2004-08-02 11:53:00) [29]

Поэтому лучше бы описать кратко задачу, которую необходимо
решить, чтобы можно было схематично описать пути решения.


OK! Ща подготовлю...


Digitman   (2004-08-02 11:49:00) [30]


> исходный код без единой ошибочки


то что "исходный код" компилируется без ошибок, вовсе не означает безошибочность работы в ран-тайм алгоритма, реализованного в этом коде


> Через синхронизатор в этом коде ведь неполучиться! Если
> только, как вы сказали, не переделать его


вот и переделывай !
любое обращение к свойствам VCL-контролов, изменяющее их виз.свойства, должно осуществляться с помощью синхронизатора .. для того и предлагает Борланд готовый метод Synchronize(), чтобы не изобретать собственный велосипед, коль того не требуют какие-то особые условия работы алгоритма в целом


panov   (2004-08-02 11:34:00) [31]

>sdw_syscoder   (02.08.04 01:24)
Задача откровенно говоря несложная.

Задача(та, которая описана в теме топика) действительно несложная, но из следующих постингов видно, что задача все же не так проста, как кажется.
Поэтому лучше бы описать кратко задачу, которую необходимо
решить, чтобы можно было схематично описать пути решения.


sdw_syscoder   (2004-08-02 11:22:00) [32]

// код нужно ПОЛНОСТЬЮ переделывать //

АААА! Может сначала из порта писать в файл, а из него уж потом поблочно преобразовывать, ведь данные имеют некую структуру. Или сразу, при чтении из массива в строку разбивать на блоки и передавать эти блоки в поток для последующей обработки.

ЗЫ: ващето лажу я наверное сморозил.


sdw_syscoder   (2004-08-02 11:03:00) [33]

не нужно бездумно сдирать код, тем более - не соответствующий требованиям Борланда по синхронизации с VCL-трэдом //

Ну конечно не соответствующий, а что Вы хотели от чайника, исходный код без единой ошибочки...

я - о слепо использованных тобой методах Lock/UnlockControl //

я не слепой! Этот метод используется для передачи параметров в VCL. Через синхронизатор в этом коде ведь неполучиться! Если только, как вы сказали, не переделать его.

код нужно ПОЛНОСТЬЮ переделывать//

В смысле переделывать, в моём понимании значит разделить на части  код обработки и код вывода в VCL. Или вообще код преобразования переделать. ИЛИ КАК?

А что код нужно переделывать это я давно понял, только вот КАК?

У Вас есть какие-нибудь варианты?


Digitman   (2004-08-02 10:38:00) [34]


> Memo.Lines.Add(DosToWin(OTA));  // функция перекодировки
> с последующим выводом в Memo, ЗДЕСЬ-ТО И НАЧИНАЕТСЯ ТОРМОЗ
> ПОСЛЕ ВЫВОДА В КОМПОНЕНТ ~50-ти СТРОК ТЕКСТА И ЕЩЁ ЗАГРУЗКА
> CPU НА 90%


не нужно бездумно сдирать код, тем более - не соответствующий требованиям Борланда по синхронизации с VCL-трэдом

я  - о слепо использованных тобой методах Lock/UnlockControl

код нужно ПОЛНОСТЬЮ переделывать


Polevi   (2004-08-02 10:35:00) [35]

аааааааааааааааааа !!!!


sdw_syscoder   (2004-08-02 10:18:00) [36]

Digitman ©, а также другие мастера, посмотрите вот этот код, занимающийся обработкой строк в потоке. Что здесь можно сделать, чтобы ускорить вывод строк в Memo, а может дело и не в Memo, а в предварительных операциях по подготовке текста к выводу.


procedure TConvertThread.Execute;
       begin
            Str_out := TStringList.Create;
            Str_gap := TStringList.Create;
            Synchronize(ReceiveForm.SMU_ErrorRead);
            // загружаем принятые данные в Str_gap
            Str_gap.Text := DataArray; // DataArray: string - в эту переменную, в первом потоке, считали из массива инфу.
            DataArray := '';
              try
                 // читаем кол-во '3A'
                 ReceiveForm.Edit3.Text:= IntToStr(Quantity(Trim(Str_gap.Text), Trim('3A')));

               // разбиваем на строки
                 begin
                 maxCount := Quantity(Trim(Str_gap.Text), Trim('3A'));
                 for I := 0 to maxCount+1 do
                 begin
                   sBroken := Str_gap.Strings[i];
                   Str_gap.Add(after(sBroken, '3A'));
                 end;
                 // аменяем остаток строки после '3A' на пустой символ ''
                 Count := Str_gap.Count;
                 Str_out.Clear;
                 for i:=1 to count-4 do
                 begin
                   sBroken := Str_gap.Strings[i];
                   Delete(sBroken,1,16); // удаление первых 16-ти символов
                   Str_out.Add(RemoveZero(ReplaceSub(sBroken, '3A', '')));
                 end;
                 Count := Str_out.Count;
                 ReceiveForm.TotalByte_edt_R.Text := IntToStr(Str_out.Count); // читаем коичество разбитых строк
                 for I := 1 to count-1 do
                 begin
                   decSTR := Str_out.Strings[i];
                   OTA := decodeCASIO(decSTR); // функция расшифровки HEX-кода
                   Memo := OutPutTo.LockControl as TMemo;
                   Memo.Lines.Add(DosToWin(OTA));  // функция перекодировки с последующим выводом в Memo, ЗДЕСЬ-ТО И НАЧИНАЕТСЯ ТОРМОЗ ПОСЛЕ ВЫВОДА В КОМПОНЕНТ ~50-ти СТРОК ТЕКСТА И ЕЩЁ ЗАГРУЗКА CPU НА 90%
                   OutPutTo.UnlockControl;
                 end;
               finally
                Str_gap.Free;
                Str_out.Free;
               end;
          end;


Digitman   (2004-08-02 09:36:00) [37]


> sdw_syscoder   (02.08.04 09:14) [6]


> т.е. SecondThread можно запустить только из FirstThread


любой новый трэд можно запустить из любого существующего трэда
и в твоем первоначальном вопросе требования выглядят так , что некий трэд А (например, основной трэд) запускает сначала FirstThread и следом, дождавшись завершения FirstThread, запускает SecondThread .. с учетом этого и дан пример


> почему у меня тормоза с выводом текста в TMemo из потока
> SecondThread


а мне почем знать ?
уж не из статьи ли Н.Кариха на этом сайте взят тобой пример реализации поточной ф-ции ?


sdw_syscoder   (2004-08-02 09:14:00) [38]

// Digitman ©   (02.08.04 08:42) [5]
т.е. SecondThread можно запустить только из FirstThread, и об окончании работы потока FirstThread, поток SecondThread получается никак не сможет узнать (например, через какой-нить флажок или параметр)?

А вот почему у меня тормоза с выводом текста в TMemo из потока SecondThread. В FirstThread происходит приём данных с порта, а в SecondThread - обработка принятых данных, с последующим выводом их в Memo.


Digitman   (2004-08-02 08:42:00) [39]


> sdw_syscoder   (02.08.04 08:29) [4]


> можно ждать события во-втором потоке, не запуская его


нельзя


> запускаем FirstThread, затем после его завершения нужно
> запустить SecondThread


// простейшее решение для случая FreeOnTerminate := false;
FirstThread := TFirstThread.Create(..);
FirstThread.WaitFor; //ждем завершения поточной ф-ции первого потока
FirstThread.Free;
SecondThread := TSecondThread.Create(..);


sdw_syscoder   (2004-08-02 08:29:00) [40]

// Забабахай named-event в каждом потоке и жди во втором окончания работы первого...

А можно ждать события во-втором потоке, не запуская его.
И объясните пожалуйста для чего нужны такие фишки, как семафор и мутекс?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо