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

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

Как передав SendMessage указатель на строку [D6]


}|{yk ©   (2004-06-22 12:25:00) 

преобразовать в функции обработчике в stroky?


}|{yk   (2004-06-22 16:07:00) [1]

Не в поток, а из потока в главный поток приложения


panov   (2004-06-22 15:53:00) [2]

>}|{yk ©   (22.06.04 15:36) [13]
Непонятно, как ты используешь SendMessage для посылки сообщения в поток.
Для этого используется PostThreadMessage:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

const WM_STRING=WM_USER+1;

type
 TForm1 = class(TForm)
   Button1: TButton;
   ListBox1: TListBox;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TTest=class(TThread)
   FListBox: TListBox;
   FMessage: String;
 protected
   procedure Execute; override;
 public
   constructor Create(const aLB: TListBox);
   procedure Display;
 end;

 TSender=class(TThread)
   FThreadId: THandle;
 protected
   procedure Execute; override;
 public
   constructor Create(const aThreadId: THandle);
 end;
var
 Form1: TForm1;
 test: TTest;

implementation

{$R *.dfm}
constructor TSender.Create(const aThreadId: THandle);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 FThreadId := aThreadId;
 Resume;
end;

procedure TSender.Execute;
var
 s: String;
 i: Integer;
begin
 for i := 0 to 1000 do
 begin
   s := IntToStr(i)+' - ????????? ?? ??????? ??????';
   PostThreadMessage(FThreadId,WM_STRING,Integer(PChar(s)),0);
 end;
 PostThreadMessage(FThreadId,WM_QUIT,Integer(@s[1]),0);
end;

constructor TTest.Create(const aLB: TListBox);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 FListBox := aLB;
 Resume;
end;

procedure TTest.Display;
begin
 FListBox.Items.Add(FMessage);
end;

procedure TTest.Execute;
var
 Msg: TMsg;
begin
 while GetMessage(Msg,0,0,0) do
 begin
   case Msg.message of
     WM_STRING:
       begin
         FMessage := PChar(Msg.wParam);
         Synchronize(Display);
       end;
   end;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Test := TTest.Create(ListBox1);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 TSender.Create(test.ThreadID);
end;

end.


Anatoly Podgoretsky   (2004-06-22 15:52:00) [3]

}|{yk ©   (22.06.04 15:36) [13]
В том контексте как ты задал вопрос сделает, вне зависимости от того какой менеджер.


Serginio666   (2004-06-22 15:49:00) [4]

Менеджер памяти ничего сам не уничтожает.
 Строка уничтожается при достижении RefCount=0;
Наступить на грабли передавая ее как указатель очень легко,
впрочем как и с динамическими массивами и интерфейсами поддерживающими подсчет ссылок.

для примера
 
 Procedure p(p:Pointer)
  var s:String;
   Begin
    Pointer(S):=P;

   //.....
   end;

По выходу из процедуры счетчик уменьшится и если он стал равен 0 то разрушиться. И вызывающем методе получишь ссылку на несуществующую память.
Здесь еще есть эффект менеджера памяти Delphi, т.к. сама память не уничтожается а помечается как не используемая
http://www.rsdn.ru/article/Delphi/memmanager.xml

Вот в общем, что и хотел сказать.


}|{yk   (2004-06-22 15:36:00) [5]

>кто её должен освободить в конце
Т.е.? Менеджер памяти Делфи не сделает это за меня?
>передаваяемая строка может выйти из области видимости(в рамках одного процесса) и самопроизвольно разрушиться.
В каком случае? Протестировал, вроде все нормально. Раньше пытался в потоке менять надписи, и иногда получал ошибки. Теперь вроде нормально


Serginio666   (2004-06-22 15:02:00) [6]

>han_malign
Согласен , данное утверждение относится к PostMessage, но
при манипуляции с классом или указателем мы увеличиваем счетчик ссылок строки предотваращая ее разрушение.
То есть
K:= TMyString.Create;
K.Str:=SourceStr;

так и с указателем.
(Конечноможно ее и вручную увеличить но это не совсем правильный подход).


han_malign   (2004-06-22 14:56:00) [7]

> Serginio666
> может выйти из области видимости
- SendMessage - выполняется "синхронно"(в контексте основного потока, но с ожиданием обработки команды). К тому же передача экземпляра класса, и дополнительные манипуляции с указателями(скажем в случае Post[Thread]Message) не спасут - тоже "может выйти из области видимости"...

З.Ы. }|{yk ©- если в строке допустимы терминирующие символы(#0), то можно, скажем в wParam, передавать длину - тогда SetString(S,PChar(lParam),wParam), или воспользоваться передачей указателя на структуру...

З.З.Ы. "UniqueString(S); // перестрахуемся... :)"- совершенно лишнее, новая строка аллокируется на /S := PChar(LParam)/SetString(...)/


Ega23   (2004-06-22 14:43:00) [8]

Serginio666   (22.06.04 14:41) [9]

Ну ты силён!!!!!!!


Serginio666   (2004-06-22 14:41:00) [9]

Создай класс
 TMyString = class
  str:String;
 end;

или PString = ^String;
И передавай экземпляр класса. Дело в том, что передаваяемая строка может выйти из области видимости(в рамках одного процесса) и самопроизвольно разрушиться.
Между процессам кроме перечисленного WMCopy


PVOzerski   (2004-06-22 12:39:00) [10]

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


Тимохов   (2004-06-22 12:38:00) [11]


> если между процессами - атомы, memory mapped files, файлы...

+wm_copydata


wicked   (2004-06-22 12:36:00) [12]

тогда подойдет [3]...
хотя это зависит от того, как и какую строку передали в SendMessage и кто её должен освободить в конце - отправитель или получатель...


PVOzerski   (2004-06-22 12:35:00) [13]

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


}|{yk   (2004-06-22 12:33:00) [14]

Между разными потоками


wicked   (2004-06-22 12:31:00) [15]

если в пределах процесса:
S := PChar(LParam);
UniqueString(S); // перестрахуемся... :)

если между процессами - атомы, memory mapped files, файлы...


MBo   (2004-06-22 12:29:00) [16]

в рамках одного процесса?


Anatoly Podgoretsky   (2004-06-22 12:26:00) [17]

S := P


Наверх

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