Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];

Вниз

Потоки (Thread)   Найти похожие ветки 

 
sdw_syscoder   (2004-08-02 01:24) [0]

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


 
GanibalLector ©   (2004-08-02 01:43) [1]

Что-то не понял вопроса...WaitForMultipleObject ???


 
GanibalLector ©   (2004-08-02 01:45) [2]

Или куда более тупиковый метод.Перед завершение потока№1 пошли сообщение(sendmessage) своей проге...а она по прихожу этого сообщения создаст второй поток.


 
3APA3A ©   (2004-08-02 02:07) [3]

Забабахай named-event в каждом потоке и жди во втором окончания работы первого... Этот метод можно использовать не то что в "разных юнитах" но и в разных приложениях...


 
sdw_syscoder   (2004-08-02 08:29) [4]

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

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


 
Digitman ©   (2004-08-02 08:42) [5]


> 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 09:14) [6]

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

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


 
Digitman ©   (2004-08-02 09:36) [7]


> sdw_syscoder   (02.08.04 09:14) [6]


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


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


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


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


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

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;


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

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


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


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


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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

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


 
panov ©   (2004-08-02 11:34) [13]

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

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


 
Digitman ©   (2004-08-02 11:49) [14]


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


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


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


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


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

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


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


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

СХЕМА ТАКАЯ:

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].

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


 
Digitman ©   (2004-08-02 12:59) [17]


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


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

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


 
panov ©   (2004-08-02 13:01) [18]

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

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

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


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

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

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


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

sdw_syscoder   (02.08.04 14:16) [19]

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


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

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


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

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


 
Digitman ©   (2004-08-02 14:39) [23]

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

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


 
Sha ©   (2004-08-02 14:45) [24]

Digitman ©   (02.08.04 14:39) [23]

Согласен.
Такое требуется только если читающие треды чужие и их несколько.


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

> Sha ©   (02.08.04 14:35) [22]
>а кто такой Thread как узнал?


Естевственно из классической литературы, ну и там... из Инета(в основном). Лень что-то искать про пост-мессаги и так уже опух.

> Digitman ©   (02.08.04 14:39) [23]
> мне вот вообще непонятно, зачем здесь нужно огород городить с несколькими доп.трэдами и синхронизацией между ними


На счёт этого замечания я тоже согласен, только вот преобразование построено так, что работает оно только тогда, когда данные приняты полностью, а не кусками.

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

Ну допустим, а тогда где производить преобразования, в методе Execute или через синхронизатор в процедуре DoRead?


 
Digitman ©   (2004-08-02 15:01) [26]


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


ну и буферизуй принимаемые "куски" в один последовательный поток (в дан.случае поток = stream, а не thread) входящих данных ! При каждом приеме анализируй, не содержит ли уже вх.поток целостных данных для обработки, и если содержит, то извлекай их из потока и обрабатывай тут же


> через синхронизатор


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


 
sdw_syscoder   (2004-08-02 15:59) [27]

А в чём отличие и преимущество потока stream от thread?


 
sdw_syscoder   (2004-08-02 16:01) [28]

Удалено модератором


 
KSergey ©   (2004-08-02 16:03) [29]

> [27],[27] sdw_syscoder

Опа, хороший вопрос... своевременный....
Может вы изначально не за те потоки схватились??


 
KSergey ©   (2004-08-02 16:04) [30]

stream - потоки ввода-вывода
thread - кодовые потоки

Сравнивать их лучше/хуже нельзя... Это как автобус и апельсин.


 
sdw_syscoder   (2004-08-02 16:18) [31]

> KSergey ©   (02.08.04 16:04) [30]

Наконец-то ситуация проясняется... Та-а-а-а-к... Ща разберёмся...

Кто не с нами, тот под нами.


 
sdw_syscoder   (2004-08-02 16:20) [32]

Если сравнивать нельзя, то скажите в каких случаях использовать stream, а в каких thread.


 
KSergey ©   (2004-08-02 16:26) [33]

Нифига, похоже, не проясняется...
Если нельзя сравнить - как можно сказать когда лучше?? Из чего лучше сделать деревянный стол: из апельсинов или автобуса? Вот так бы я переформулировал этот вопрос. Надеюсь, теперь его абсурдность понятна?

Вы про них просто прочитайте
Зачем здесь просить пересказ статей, коих в инете навалом. И в книгах.


 
Digitman ©   (2004-08-02 16:28) [34]


> sdw_syscoder


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


 
sdw_syscoder   (2004-08-02 16:41) [35]

> Digitman ©   (02.08.04 16:28) [34]

Ну ты и загнул, я ваще впервые слышу об FIFO-очереди, где-нибудь можно вычитать формулировку?

> KSergey ©   (02.08.04 16:26) [33]

Уважаемый KSergey ©, не знаю как Вам, а по-моему после [34] постера уже понятно что к чему и в каком направлении идти.

Но я всё-таки попробую переписать код под Thread-овский поток, а после буду разбираться со Stream-овским.


 
Erik1   (2004-08-02 16:59) [36]

У меня стояла аналогтчная задача. Я сичтывал кусками и записывал в pipe великолепная вещь для таких случиев. Когда блок будет принят записывай его в буфер и передавай в форму PostMessage() Память под буфер можно выделять через GetMem а указатель передавать в PostMessage, при принятии незабудь очистить память и занести в memo.


 
Anatoly Podgoretsky ©   (2004-08-02 17:07) [37]

Так совсем мужика запутали, теперь еще и про трубы узнавать :-)


 
Digitman ©   (2004-08-02 17:20) [38]


> ваще впервые слышу об FIFO


если ты в 1-й раз слышишь о стримах, об PostMessage(), то не лучше ли отказаться на время от задачи, вызывающей на сей день массу непонятностей и явно непосильной тебе, взять соотв.литературу и внимательно почитать ее ?


 
sdw_syscoder   (2004-08-02 17:20) [39]

> Anatoly Podgoretsky ©   (02.08.04 17:07) [37]
Внатури, глаза разбегаются с чего начинать, я с Thread-ом ещё не до конца разобрался, а тут трубы подогнали... Вот гемморой-то а-а-а?

> Erik1   (02.08.04 16:59) [36]
У меня стояла аналогтчная задача. Я сичтывал кусками и записывал в pipe...


Т-а-а-к... Я балдею! Что ещё за ПИПЕ? Ха-ха! Может примерчик свой аналогичный подкинете, а то я "сечку" весь день жру.


 
Anatoly Podgoretsky ©   (2004-08-02 17:22) [40]

sdw_syscoder   (02.08.04 17:20) [39]
Говори спасибо, что не IPC или COM сервер



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.034 c
4-1089046492
ИМХО
2004-07-05 20:54
2004.08.15
CLSID


1-1091491749
Almaz
2004-08-03 04:09
2004.08.15
Выбор Published свойств, определенных в конкретном классе


1-1091439114
FeSSik
2004-08-02 13:31
2004.08.15
Вопрос про EXE файл.


3-1090178737
Комбинатор
2004-07-18 23:25
2004.08.15
Как узнать прошёл ли commit или нет...


4-1088760245
Rain
2004-07-02 13:24
2004.08.15
Компонент для работы с модемом





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский