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

Вниз

Передача сообщений из TThread в визуальные компоненты   Найти похожие ветки 

 
IgorP   (2005-02-26 20:28) [0]

Уважаемые мастера, не подскажете ли как из потока TThread правильно вывести сообщения, например в TMemo.

Сообщения простые. Типа
"Поток запустился"
"Поток протекает успешно"
"Поток закрылся"

Запускается поток процедурой CreateThread(..@"процедура"..)

Я пока ещё не мастер, и поэтому просто в "процедуре" (потоке) пишу :
Form1.Memo1.Lines.Add("...")

В результате на этой строке моё приложение виснет.

С уважением, Игорь


 
DiamondShark ©   (2005-02-26 21:18) [1]

Во-первых, лучше создавать потоки функцией BeginThread.
Во-вторых, и борланд этот момент упоминает в документации, обращения к VCL компонентам должны синхронизироваться с основным потоком.


 
Mim2   (2005-02-27 02:57) [2]

// Передача сообщений из TThread в визуальные компоненты
что то не клеется упрминание класса tthread в топике
с
// Запускается поток процедурой CreateThread(..@"процедура"..)


 
GanibalLector ©   (2005-02-27 03:55) [3]

>Я пока ещё не мастер, и поэтому просто в "процедуре" (потоке) пишу :Form1.Memo1.Lines.Add("...")

Так нельзя.Отсылай сообщение форме.В форме обрабатывай это сообщение и заполняй Memo.


 
Юрий Зотов ©   (2005-02-27 05:55) [4]

> IgorP   (26.02.05 20:28)

При создании потока передайте ему хэндл формы, которой он будет отправлять сообщения. Остальное просто, например так:
PostMessage(WndHandle, WM_USER+200, 0, 1);
Получив сообщение, форма знает, что означает число в LParam и выводит в Memo нужную строку.

Только не используйте SendMessage, иначе поток остановится и будет ждать, пока форма обработает сообщение.


 
Набережных С. ©   (2005-02-27 06:55) [5]


> IgorP
> Form1.Memo1.Lines.Add("...")

Хотя так делать не правильно, но зависание сама по себе такая строка вряд-ли может вызвать. Что-то ты не договариваешь.


 
sniknik ©   (2005-02-27 10:58) [6]

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

более полный исходный код ошибки конечно бы не помешал.


 
Набережных С. ©   (2005-02-27 11:12) [7]


> sniknik ©   (27.02.05 10:58) [6]

Шрифт - это другое. Зависание происходит из-за блокировки канвы, а Memo.Lines.Add использует для добавления SendMessage и вся перерисовка происходит в главном потоке. Так что никаких зависаний.


 
atruhin ©   (2005-02-27 11:12) [8]

А почему никто не сказал человеку про существование Sinhronize?
Хотя стандарные сообщения лучше конечно выводить через PostMessage, но ведь в следующем топике он спросит как вывести, резулитат :)


 
Набережных С. ©   (2005-02-27 11:21) [9]


> atruhin ©   (27.02.05 11:12) [8]

Потому, что

> Запускается поток процедурой CreateThread(..@"процедура"..)


 
atruhin ©   (2005-02-27 11:36) [10]

>>Набережных С. ©   (27.02.05 11:21) [9]
Понял, торможу. Не заметил.


 
Defunct ©   (2005-02-27 11:39) [11]

> а Memo.Lines.Add использует для добавления SendMessage и вся перерисовка происходит в главном потоке.
Так что никаких зависаний.


Ерунду городите.
попробуйте сами Memo.Lines.Add из другого потока выполнить. Зависнет как пить дать в 3х случаях из 4х.


 
Набережных С. ©   (2005-02-27 12:01) [12]


> Defunct ©   (27.02.05 11:39) [11]

Ерунду городите как раз Вы.
Если Вам не хватает ума просто посмотреть и проанализировать исходники, а также понять причины блокирок в VCL, то сами проведите такой опыт хоть 4, хоть 4000 раз. А я уже это делал. Я вообще не имею привычки утверждать безоговорочно что-то, чего не знаю. В отличии от Вас.
LMD.


 
sniknik ©   (2005-02-27 13:36) [13]

Набережных С. ©   (27.02.05 11:12) [7]
> а Memo.Lines.Add использует для добавления SendMessage и вся перерисовка происходит в главном потоке. Так что никаких зависаний.
 <>
Юрий Зотов ©   (27.02.05 05:55) [4]
> Только не используйте SendMessage, иначе поток остановится и будет ждать, пока форма обработает сообщение.

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


 
Leonid Troyanovsky ©   (2005-02-27 13:42) [14]


> Набережных С. ©   (27.02.05 11:12) [7]
> канвы, а Memo.Lines.Add использует для добавления SendMessage
> и вся перерисовка происходит в главном потоке. Так что никаких
> зависаний.


Зависаний, конечно, быть не должно.
Однако, Memo.Lines.Add, в отличии от, скажем, ListBox.Items.Add
вынуждено пользовать более одного сообщения.
А тогда, между двумя этими сообщениями, возможно изменение
выделения (другим потоком):

SendMessage(Memo.Handle, EM_SETSEL, SelStart, SelStart);
SendMessage(Memo.Handle, EM_REPLACESEL, 0, Longint(PChar(Line)));

что чревато потерей данных в Memo. (Сюрприз :)

--
С уважением, LVT.


 
Набережных С. ©   (2005-02-27 13:57) [15]


> sniknik ©   (27.02.05 13:36) [13]

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

> почемуто ужастно не хочется практически проверять

Да ладно, нас таким не запугаешь:) Вот тебе пример, 5 минут делов:

function ThrFunction(P: Pointer): DWORD; stdcall;
var
 S: string;
 D: DWORD;
 n: integer;
begin
 Form1.Memo1.Lines.Add("Start");
 for n:=0 to 99 do
 begin
   D:=Random(500);
   Sleep(D);
   s:="Step " + IntToStr(n);
   Form1.Memo1.Lines.Add(s);
 end;
 Form1.Memo1.Lines.Add("Finish");
 Result:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 ID, H: Cardinal;
 n: integer;
begin
 IsMultiThread:=true;
 Randomize;
 for n:=0 to 9 do
 begin
   H:=CreateThread(nil, 0, @ThrFunction, nil, 0, ID);
   CloseHandle(H);
 end;
end;


> возможно "завис" в другом месте (например строчка до этой
> ;о), а мы тут спорим)

:))


 
Набережных С. ©   (2005-02-27 14:00) [16]


> Leonid Troyanovsky ©   (27.02.05 13:42) [14]

Не понятно, что Вы хотите мне сказать. Я, кажется, и не говорил, что так делать правильно, а? И возможные последствия прекрасно сознаю. К чему Вы это?


 
Набережных С. ©   (2005-02-27 14:08) [17]

И, кстати, вызовов SendMessage там больше двух, потому как есть еще и GeTCount, в который тоже можно вклиниться, и это может привести к потере данных.


 
Leonid Troyanovsky ©   (2005-02-27 14:13) [18]


> Юрий Зотов ©   (27.02.05 05:55) [4]
> Только не используйте SendMessage, иначе поток остановится
> и будет ждать, пока форма обработает сообщение.


Что, собс-но, не всегда плохо.
А вот PostMessage может привести, скажем, к переполнению стека.

--
Regards, LVT.


 
Набережных С. ©   (2005-02-27 14:24) [19]


> Leonid Troyanovsky ©   (27.02.05 14:13) [18]
> А вот PostMessage может привести, скажем, к переполнению
> стека.

Это каким образом?


 
Leonid Troyanovsky ©   (2005-02-27 14:24) [20]


> Набережных С. ©   (27.02.05 14:08) [17]
> И, кстати, вызовов SendMessage там больше двух, потому как
> есть еще и GeTCount, в который тоже можно вклиниться, и
> это может привести к потере данных.


"Там" это где?
delphi6\source\vcl\StdCtrls.pas

function TListBoxStrings.Add(const S: string): Integer;
begin
 Result := -1;
 if ListBox.Style in [lbVirtual, lbVirtualOwnerDraw] then exit;
 Result := SendMessage(ListBox.Handle, LB_ADDSTRING, 0, Longint(PChar(S)));
 if Result < 0 then raise EOutOfResources.Create(SInsertLineError);
end;

И, в любом случае, вызов GetCount никак не может привести
к потере данных. В крайнем случае, к вставке не в то место.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-02-27 14:31) [21]


> Набережных С. ©   (27.02.05 14:24) [19]
> > А вот PostMessage может привести, скажем, к переполнению  
> > стека.

> Это каким образом?


Если окно будет обрабатывать сообщение дольше периода
их отсылки, то очередь сообщений будет расти, расти
и, в конце-концов, вырастет.

--
Regards, LVT.


 
Набережных С. ©   (2005-02-27 14:40) [22]


> Leonid Troyanovsky ©   (27.02.05 14:24) [20]

"Там" - это в TМемо.Lines.Add, в которой сначала вызывается GetCount, а потом Insert.  Если, например, после GetCount, другой поток удалит несколько строк, то индекс для Insert окажется невалидным и строка не будет добавлена.

> Leonid Troyanovsky ©   (27.02.05 14:31) [21]
> Если окно будет обрабатывать сообщение дольше периода
> их отсылки, то очередь сообщений будет расти, расти
> и, в конце-концов, вырастет.

Допустим, хотя очереди довольно вместительные. А стек при чем?


 
Leonid Troyanovsky ©   (2005-02-27 15:12) [23]


> Набережных С. ©   (27.02.05 14:40) [22]
> Допустим, хотя очереди довольно вместительные. А стек при
> чем?


Стек здесь, конечно, ни причем.
Ну, пусть это будет хоть system cache resident bytes.
Все равно, ограниченный ресурс.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2005-02-27 15:28) [24]


> Набережных С. ©   (27.02.05 14:40) [22]

> "Там" - это в TМемо.Lines.Add, в которой сначала вызывается
> GetCount, а потом Insert.  Если, например, после GetCount,
> другой поток удалит несколько строк, то индекс для Insert
> окажется невалидным и строка не будет добавлена.


Я ж привел код для ListBox.Items.Add.
Где там Insert, GetCount?

Или, что значит


> Набережных С. ©   (27.02.05 14:08) [17]
> И, кстати, вызовов SendMessage там больше двух, потому как
> есть еще и GeTCount, в который тоже можно вклиниться, и


Кстати, "более двух" => "более одного", если уж понимать
это как Memo.Lines.Add.

Который был "в отличии от, скажем, ListBox.Items.Add"

--
Regards, LVT.


 
Набережных С. ©   (2005-02-27 15:49) [25]

Леонид, но ведь речь то шла о TMemo? Вы же сами показали вызовы для Tmemo в [14], на который я и ссылался, при чем же тут ListBox? Весь топик ведь о Memo...
На счет стека, как я понимаю, оговорка? Ну такое и со мной бывает:(


 
Leonid Troyanovsky ©   (2005-02-27 15:51) [26]


> Набережных С. ©   (27.02.05 14:40) [22]
> "Там" - это в TМемо.Lines.Add, в которой сначала вызывается
> GetCount, а потом Insert.  Если, например, после GetCount,
> другой поток удалит несколько строк, то индекс для Insert
> окажется невалидным и строка не будет добавлена.


Если, например, индекс окажется невалидным, то
If there is no current selection, the replacement text is
inserted at the current location of the caret.

Т.е., опасность не в потере добавляемого, а в
замещении выделенного, о чем и говорилось ранее.

--
Regards, LVT.

PS Теперь, видимо, я готов сказать то, что я и хотел сказать. Т.е., к совету уважаемого GanibalLector можно добавить,
что если взять, например, ListBox, то Items.Add можно хоть из
вторичного потока.


 
Leonid Troyanovsky ©   (2005-02-27 16:01) [27]


> Набережных С. ©   (27.02.05 15:49) [25]

> Леонид, но ведь речь то шла о TMemo? Вы же сами показали
> вызовы для Tmemo в [14], на который я и ссылался, при чем
> же тут ListBox? Весь топик ведь о Memo...

Просто я воспринял "более двух" как относимое к ListBox.
Ведь, для Memo вполне достаточно "более одного".
Ну, теперь, наверное, все прояснилось.  

> На счет стека, как я понимаю, оговорка? Ну такое и со мной
> бывает:(

У меня, к сожалению, бывают и не только оговорки ;)

--
Regards, LVT.


 
Набережных С. ©   (2005-02-27 16:19) [28]


> Т.е., опасность не в потере добавляемого, а в
> замещении выделенного, о чем и говорилось ранее.

Не совсем так, к сожалению:( Ниже часть кода из TMemoStrings.Insert

 if Index >= 0 then
 begin
   SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index, 0);
   if SelStart >= 0 then Line := S + #13#10 else
   begin
     SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, Index - 1, 0);
     if SelStart < 0 then Exit;
     LineLen := SendMessage(Memo.Handle, EM_LINELENGTH, SelStart, 0);
     if LineLen = 0 then Exit;
     Inc(SelStart, LineLen);
     Line := #13#10 + s;
   end;

На выделенной строке она и может закончить выполние при определенных условиях, если индекс окажется слишком велик, причем без возможности об этом узнать:(

Что-то больно далеко мы ушли от темы, при этом каждый говорит о своем:) Порежут нас нафиг, и правильно сделают:) Давайте закончим.


 
Defunct ©   (2005-03-04 06:07) [29]

Набережных С. ©   (27.02.05 14:40) [22]

> Я вообще не имею привычки утверждать безоговорочно что-то, чего не знаю. В отличии от Вас.

Тем хуже для Вас.

Безоговорочно ложное утверждение приводит к спору, в котором вытягиваешь, порой очень ценные, сведения и нюансы. Главное правильно адресовать.

PS: А ведь в моем посте нотки провокации так и сверкают: "в 3х случаях из 4х." - не бывает такого. Спасибо, что съэкономили мое время.



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

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

Наверх





Память: 0.54 MB
Время: 0.075 c
1-1109758349
Jann
2005-03-02 13:12
2005.03.20
Декомпилятор


3-1109046479
pluto
2005-02-22 07:27
2005.03.20
Сортировка по убыванию


3-1108881148
Sour
2005-02-20 09:32
2005.03.20
Mapping объектов в РСУБД


1-1110167611
X-Disa
2005-03-07 06:53
2005.03.20
Компонент для выбора цвета


14-1109871817
Жук Андрій
2005-03-03 20:43
2005.03.20
Кто-то хотел скачать фото нашего Президента в высоком качестве?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский