powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lazarus: передача blob, как параметра, внутрь и наружу TThread
39 сообщений из 39, показаны все 2 страниц
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509166
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Решил полностью перенести логику чтения/записи из/в БД в доп.потоки.

С передачей обычных типов проблем нет
Код: pascal
1.
TThread.Create(CreateSuspended: boolean; AParamsArr: Array of Variant;......);



Как запихать сабж в параметр и/или передать его в основной поток?
=================
Док.

Win7 Ultim x64/Deb 8.7 i386:
FB 3.0.2.32703, диалект 3, SS(win)/SC(Deb),
Lazarus 1.9(r.55538); FPC 3.1.1 (r.36290), IBX by -Rik-; IBE 2017.4.19.2
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509170
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как поток...

Который TMemoryStream то есть.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509172
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanКак поток...

Который TMemoryStream то есть.
вот гад Ты пальцем покажи, не догоняю ..
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509193
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,
поток - стрим,
нить - тред.

Такие дела.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509215
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокКак запихать сабж в параметр
В старом дельфевом (когда было String=AnsiString) IBX работало
ParamByName( 'BLOBFIELD' ).AsString := SBlobData,
где SBlobData - любые (можно и бинарные) данные блоб.
Может сработать
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509233
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччД,

т.е. затроллить решили? Ладно-ладно ...

YuRockМожет сработать
а если там бинарных данных на десяток мегабайт? Я смогу впихнуть невпихуемое в параметр?

зы. я-то надеялся, можно указатель какой передать или где. А так придется на буржуйский форум идти :(
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509235
DesWind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Док,

Блоб-поля можно вводить и выводить через TStream, Например TMemoryStream.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509239
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DesWind,

ты хоть словами скажи (хотя бы схематично), что-как-где создать сначала, куды запихнуть потом. При этом так, чтобы анимашка крутилась и сообщения юзверю показывала. Я реально че-та затупил...
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509271
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокYuRockМожет сработать
а если там бинарных данных на десяток мегабайт? Я смогу впихнуть невпихуемое в параметр?

зы. я-то надеялся, можно указатель какой передать или где. А так придется на буржуйский форум идти :(
десяток мегабайт - это не так уж и много.
Вот если на гигабайты счет - тогда плохо. Для этого уже только TBlobField.LoadFromStream.
Но, блин, что за база такая ( на FB ), в которую гигабайтами блобы льют - страшно представить)
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509276
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокЯ смогу впихнуть невпихуемое в параметр?
Зависит от того, сработает ли на твоём IBX такое. У меня работает.
На моём отлично работает так:
Код: pascal
1.
2.
FInsertCommand.ParamByName( 'BLOB_DATA' ).AsString := SBlobData;
FInsertCommand.ExecQuery;


где SBlobData - неюникодный стринг,
FInsertCommand - один раз препарированный TIBSQL с инсертом и параметром.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509296
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не вижу проблемы вытащить из базы:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    qTasksPAYLOAD: TOraMemoField; { TMemoField, TBlobField, ... }
....
        if qTasksPAYLOAD.BlobSize > 0 then
        begin
          Context.TaskStream := TMemoryStream.Create;
          Context.TaskStream.Size := qTasksPAYLOAD.BlobSize;
          qTasksPAYLOAD.SaveToStream(Context.TaskStream);
        end
        else
          Context.TaskStream := nil;



Поместить в базу еще проще:

Код: pascal
1.
  qTasksPAYLOAD.LoadFromStream (Context.TaskStream);



далее стандартные операции TDataSet
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509313
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ага, спасибо. Ушел думать ...
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509374
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В UIB у полей есть такие свойства как AsStream и AsBytes - но не уверен, что он соберется на Лазаре.

В любом случае - если речь идет о бооольших блобах, то задержка может быть и на дисковой операции, и на сетевой (БД)

Т.е. там нужно в отдельной нити (thread) сделать отдельное соединение с БД, и уже в этом отдельном соединении грузить блоб.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509392
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiПоместить в базу еще проще:

Код: pascal
1.
  qTasksPAYLOAD.LoadFromStream (Context.TaskStream);


Да, но в таком варианте много неявных и явных "лишних" операций:
- открыть запрос
- сделать Append
- заполнить поля
- сделать Post
- перед всем этим оформить InsertSQL правильно...

В случае препарированного инсерта ничего этого делать не надо.
задал параметр - и Exec, всё.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509405
Любезный
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Каждый коннект должен быть в своем Thread, и это правильно.
2. Вроде у TField должны быть методы LoadFromStream и SaveToStream.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509411
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтение
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
      LStrm := TIBBlobStream.Create;
      try
        LStrm.Mode := bmRead;
        LStrm.Database := ADS.Database;
        LStrm.Transaction := ADS.Transaction;
        LStrm.BlobID := AField.AsQuad;
        LStrm.ReadBuffer(.........);
      finally
        LStrm.Free;
      end;

Запись
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
      LStrm := TIBBlobStream.Create;
      try
        LStrm.Mode := bmWrite;
        LStrm.Database := ADS.Database;
        LStrm.Transaction := ADS.Transaction;
        LStrm.WriteBuffer(.......);
        LStrm.Finalize;
        AField.AsQuad := LStrm.BlobID;
      finally
        LStrm.Free;
      end;

Соответственно TIBBlobStream создаешь в потоке, а обмениваешься BlobID (AsQuad). Как это все будет работать в многопотоке - хз.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509413
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для датасетов такой способ
Код: pascal
1.
LStrm := AField.DataSet.CreateBlobStream(AField, bmWrite);

И потом этот стрим отдаешь в поток. Дисклаймер тот же_Vasilisk_Как это все будет работать в многопотоке - хз.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509414
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_Для датасетов такой способТолько не забудь потом вызвать
Код: pascal
1.
LStrm.Free;
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509417
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockschiПоместить в базу еще проще:

Код: pascal
1.
  qTasksPAYLOAD.LoadFromStream (Context.TaskStream);


Да, но в таком варианте много неявных и явных "лишних" операций:
- открыть запрос
- сделать Append
- заполнить поля
- сделать Post
- перед всем этим оформить InsertSQL правильно...

В случае препарированного инсерта ничего этого делать не надо.
задал параметр - и Exec, всё.

Виноват, DataSet, которым я пользуюсь, понимает, что запись в поле это задание параметров для запроса вставки/обновления. Аналог TUpdateSQL.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509522
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

за IBBlobStream спасибо, не знал. Надо будет посмотреть в том форке, который у меня в Лазаре стоит.

Проблемы в доп.потоке создать/уничтожить компоненты доступа и коннект нет. Есть проблема обмена блобами между потоками. Пошел шарить по исходникам.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509540
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док, что такое "блоб"?
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509573
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiВиноват, DataSet, которым я пользуюсь
Вот в том то и дело. А для insert'а в базу DataSet не нужен.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509579
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДДок, что такое "блоб"?
Бинарные данные произвольного размера (форматированный текст, картинки и проч.)
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509603
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокчччДДок, что такое "блоб"?
Бинарные данные произвольного размера (форматированный текст, картинки и проч.)

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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  fQ_IBX : TIBSQL; // IBX
  fQ_FIB : TpFIBQuery; // FIB+

  fMS : TMemoryStream;
begin
  fMS := TMemoryStream.Create;
...
  fQ_IBX.FieldByName('blob_field_1').SaveToStream(fMS);
...
  fQ_FIB.FieldByName('blob_field_2').SaveToStream(fMS);


И передавай в нить этот самый fMS.

Если блок данных очень уж велик, то сохраняй в файл:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  fQ_IBX : TIBSQL; // IBX
  fQ_FIB : TpFIBQuery; // FIB+

  fFS : TFileStream;
begin
  fFS := TFileStream.Create(<имя временного файла>, fmCreate);
...
  fQ_IBX.FieldByName('blob_field_1').SaveToStream(fFS);
...
  fQ_FIB.FieldByName('blob_field_2').SaveToStream(fFS);


... или даже в файл, который будет автоматически удаляться, кода он станет не нужным:

Код: pascal
1.
2.
3.
4.
5.
var
  fH : Handle;
begin
  fH := CreateFile(<имя временного файла>, GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0);
  fFS := TFileStream.Create(fH);


... а то и просто хэндл файла передавай.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509618
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRockschiВиноват, DataSet, которым я пользуюсь
Вот в том то и дело. А для insert'а в базу DataSet не нужен.

Может и не нужен, но с ним удобнее. Я не до конца понимаю, о чем дискуссия, правда :)
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39509624
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччД,

во, спасибо. Завтра, когда моск включится, посмотрю твой код. Очень интересная реализация.

зы. Вариант с временным файлом у меня давно реализован. Хочу уйти от него, т.к. могут быть потенциальные проблемы с правами на запись и проч.проч.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511787
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм, вообщем, попробовал идею чччД. Получилось примерно так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
const
  {uses windows for WIN or LMessages for LINUX}
  WM_ADDSTREAMPARAM_MSG = WM_USER + $101;
  WM_CONTAINERCLEAR_MSG = WM_USER + $102;


type

  TStreamRec = packed record
    ContainerType: Integer;
    ByteArray: array of Byte;
  end;

  { TMyThread }

  TMyThread = class(TThread)
  private
    FArrStreamRec: array of TStreamRec;
  protected
    procedure Execute; override;
  public
    FIsTermThread: Boolean;
    constructor Create (CreateSuspended: boolean; ArrStreamRec: array of TStreamRec);
  end;

  { TForm1 }

  TForm1 = class(TForm)
//<skiped>
  private
    FMyThread: TMyThread;
  public
    procedure WM_AddStreamParam_Msg (var Msg: TLMessage); message WM_ADDSTREAMPARAM_MSG;
    procedure WM_ContainerClear_Msg (var Msg: TLMessage); message WM_CONTAINERCLEAR_MSG;
  end; 

procedure TForm1.BtnThreadClick(Sender: TObject);
var
  msM //поток для Memo
  //, dms
  , msP: TMemoryStream; //поток для Picture

  MyStreamArr: array of TStreamRec;
begin
  if Assigned(FMyThread) then Exit;

  msM:= TMemoryStream.Create;//для строк
  //dms:= TMemoryStream.Create;
  msP:= TMemoryStream.Create;//для картинки
  try
    //    ===== MemoSrc ====
    MemoSrc.Lines.SaveToStream(msM);
    msM.Position:= soFromBeginning;

    SetLength(MyStreamArr, 2);//размер array of TStreamRec
    SetLength(MyStreamArr[0].ByteArray,msM.Size);//определяем размер массива байтов поля array of TStreamRec
    msM.Read(MyStreamArr[0].ByteArray[0],msM.Size);//читаем содержимое потока в массив поля записи
    MyStreamArr[0].ContainerType:= 0;//тип контейнера Memo

    //    ===== MemoSrc ====
    ImgSrc.Picture.SaveToStream(msP);
    msP.Position:= 0;

    SetLength(MyStreamArr[1].ByteArray, msP.Size);
    msP.Read(MyStreamArr[1].ByteArray[0],msP.Size);
    MyStreamArr[1].ContainerType:= 1;

    //создаем поток с параметрами и ждем результаты
    FMyThread:= TMyThread.Create(True,MyStreamArr);

    try
      while not FMyThread.FIsTermThread do
      begin
        Application.ProcessMessages;
        Sleep(500);
      end;
    finally
      FreeAndNil(FMyThread);
    end;

    //вот так все копируется в новый контейнер корректно
    //dms.Write(MyStreamArr[0].ByteArray[0],Length(MyStreamArr[0].ByteArray));
    //dms.Position:= soFromBeginning;
    //ImgDest.Picture.LoadFromStream(dms);
  finally
    FreeAndNil(msP);
    //FreeAndNil(dms);
    FreeAndNil(msM);
  end;
end;    

procedure TForm1.WM_ContainerClear_Msg(var Msg: TLMessage);
begin
  case Msg.wParam of
    0: begin
      MemoDest.Clear;
      Label1.Caption:= 'грузим Memo';
    end;
    1: begin
      ImgDest.Picture.Clear;
      Label1.Caption:= 'грузим картинку';
    end;
  end;
end;

constructor TMyThread.Create(CreateSuspended: boolean;
  ArrStreamRec: array of TStreamRec);
var
  i: Integer;
begin
  inherited Create(CreateSuspended);
  Priority:= tpLower;
  FreeOnTerminate:= False;
  FIsTermThread:= False;

  if Length(ArrStreamRec) > 0 then
    begin
      SetLength(FArrStreamRec,Length(ArrStreamRec));

      for i := Low(ArrStreamRec) to High(ArrStreamRec) do
        begin
          FArrStreamRec[i].ContainerType:= ArrStreamRec[i].ContainerType;
          SetLength(FArrStreamRec[i].ByteArray,Length(ArrStreamRec[i].ByteArray));//надо ли определять размер?
          FArrStreamRec[i].ByteArray:= ArrStreamRec[i].ByteArray;
        end;
    end;

  if CreateSuspended then Start;
end; 

procedure TForm1.WM_AddStreamParam_Msg(var Msg: TLMessage);
var
  ARec: TStreamRec;
  ms: TMemoryStream;
begin

  ARec:= TStreamRec(Pointer(Msg.lParam)^);

  ms:= TMemoryStream.Create;
  try
    ms.Write(ARec.ByteArray[0],Length(ARec.ByteArray));
    ms.Position:= soFromBeginning;

    case Msg.wParam of
      0: MemoDest.Lines.LoadFromStream(ms);
      1: ImgDest.Picture.LoadFromStream(ms);
    end;
  finally
    FreeAndNil(ms);
  end;
end;                                             



Чую, где-то косяк при передаче парамметров в WM_AddStreamParam_Msg. В Memo отображается "????", картинка пустая.

ЧЯДНТ?

зы. архив приложил
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511803
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

Навскидку вроде я не заметил огрехов. Но мне непонятно другое - зачем такой огород, почему тип нужных данных не передавать сразу в Stream хотя бы через Integer

то есть,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  ContentType: Integer;
//для текста
  ContentType := 0;
Stream.Write (ContentType, SizeOf(ContentType));
Memo1.Lines.SaveToStream(Stream);

//для картинки
 ContentType := 1;
  Stream.Write (ContentType, SizeOf(ContentType));  
  Image1.Picture.SaveToStream(Stream);



К чему все эти сообщения и прочий геморрой ?
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511820
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiК чему все эти сообщения и прочий геморрой ?
тут дело в постановке задачи. Скажем так, в данном случае, мне нужно передать массив байтов (или указатель на TMemoryStream, все равно его экземпляр будет жить до окончания жизни доп.потока) в доп.поток и вернуть его обратно. Т.о. образом я смогу, когда надо, передать blob в доп.поток (скажем, при записи в таблицу), а когда надо - передать blob в основной поток (например, при чтении из БД).

зы. если ты смотрел сорцы приложенного архива, там есть вариант прямого копирования из контейнера в контейнер.
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511834
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокschiК чему все эти сообщения и прочий геморрой ?
тут дело в постановке задачи. Скажем так, в данном случае, мне нужно передать массив байтов (или указатель на TMemoryStream, все равно его экземпляр будет жить до окончания жизни доп.потока) в доп.поток и вернуть его обратно. Т.о. образом я смогу, когда надо, передать blob в доп.поток (скажем, при записи в таблицу), а когда надо - передать blob в основной поток (например, при чтении из БД).

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

Смотрел, но не разбирался. Относительно потоков и прочих массивов - у всех потоков в процессе память общая, указатели можно передавать туда и сюда. Для blob'в хорошо подходят Stream-ы потому что их уже поддерживают blob-поля.
Вот честно не понимаю, в чем проблема, с передачей разного рода объектов между потоками (да и между процессами тоже) имею дело давно, поэтому возможно чего-то у тебя не понимаю :)
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511844
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiВот честно не понимаю, в чем проблема
Хорошо, покажи (хотя бы схематично), как ты передаешь блобы из главного в доп. поток (если пишешь в базу) или из доп.потока в основной поток (если читаешь). Я с этим вопросом только начал разбираться, не совсем вкурил
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511847
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
хех, голова садовая, забыл Execute доп.потока показать
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
{ TMyThread }

procedure TMyThread.Execute;
var
  msg: TLMessage;
begin
  msg.wParam:= FArrStreamRec[0].ContainerType;
  SendMessage(Form1.Handle,WM_CONTAINERCLEAR_MSG,msg.wParam,0);//чистим контейнер (это memo)
  SendMessage(Form1.Handle,WM_ADDSTREAMPARAM_MSG,0,DWORD(@FArrStreamRec[0]));
  Sleep(2000);

  msg.wParam:= FArrStreamRec[1].ContainerType;
  SendMessage(Form1.Handle,WM_CONTAINERCLEAR_MSG,msg.wParam,0);//чистим контейнер (это Picture)
  SendMessage(Form1.Handle,WM_ADDSTREAMPARAM_MSG,0,DWORD(@FArrStreamRec[1]));
  Sleep(2000);

  FIsTermThread:= True;
end;


schi,
глянь, плз, корректно ли я передаю параметры в основной поток и корректно ли там их принимаю
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
procedure TForm1.WM_AddStreamParam_Msg(var Msg: TLMessage);
var
  ARec: TStreamRec;
  ms: TMemoryStream;
begin

  ARec:= TStreamRec(Pointer(Msg.lParam)^);

  ms:= TMemoryStream.Create;
  try
    ms.Write(ARec.ByteArray[0],Length(ARec.ByteArray));
    ms.Position:= soFromBeginning;

    case Msg.wParam of
      0: MemoDest.Lines.LoadFromStream(ms);
      1: ImgDest.Picture.LoadFromStream(ms);
    end;
  finally
    FreeAndNil(ms);
  end;
end; 

...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511857
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДокschiВот честно не понимаю, в чем проблема
Хорошо, покажи (хотя бы схематично), как ты передаешь блобы из главного в доп. поток (если пишешь в базу) или из доп.потока в основной поток (если читаешь). Я с этим вопросом только начал разбираться, не совсем вкурил

Работа с базой:
20743953

между потоками передается указатель на некий контекст (AContext в коде), это запись, одно из полей которой - указатель на Stream.

Разумеется, я опустил синхронизацию, но полагаю, что это азы.

Докглянь, плз, корректно ли я передаю параметры в основной поток и корректно ли там их принимаю


На мой беглый взгляд корректно, но почему бы тебе не сделать логирование и самому посмотреть ?
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511869
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

Набросал пример на скорую руку, работающий:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
unit main;

interface

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

const
  UM_BEGIN = WM_USER + 1;
  UM_INCOMINGSTREAM = WM_USER;

type
  TProducerThread = class(TThread)
  protected
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormShow(Sender: TObject);
  private
    procedure UMBegin (var Message: TMessage); message UM_BEGIN;
    procedure UMIncomingStream (var Message: TMessage); message UM_INCOMINGSTREAM;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TProducerThread }

procedure TProducerThread.Execute;
var
  SR: TSearchRec;
  ErrCode: Integer;
  DataDir: string;
  FS: TFileStream;
  MS: TMemoryStream;
begin
  DataDir := ExtractFilePath(ParamStr(0))+'Data\';
  ErrCode := FindFirst(DataDir+'*.*', faAnyFile, SR);
  while (ErrCode = 0) and not Terminated do
  begin
    if (SR.Attr and faDirectory) = 0 then
    begin
      FS := TFileStream.Create(DataDir + SR.Name, fmOpenRead);
      try
        MS := TMemoryStream.Create;
        try
          MS.SetSize(FS.Size);
          MS.CopyFrom(FS, FS.Size);
          MS.Position := 0;
          SendMessage(Application.MainForm.Handle, UM_INCOMINGSTREAM, 0, LPARAM(MS));
        except
          MS.Free;
          raise;
        end;
      finally
        FS.Free;
      end;
    end;
    ErrCode := FindNext(SR);
  end;
end;

{ TForm1 }

procedure TForm1.FormShow(Sender: TObject);
begin
  PostMessage(Handle, UM_BEGIN, 0, 0);
end;

procedure TForm1.UMBegin(var Message: TMessage);
var
  Thread: TProducerThread;
begin
  Thread := TProducerThread.Create(True);
  Thread.FreeOnTerminate := True;
  Thread.Resume;
end;

procedure TForm1.UMIncomingStream(var Message: TMessage);
begin
  with Message do
    Memo1.Lines.LoadFromStream(TStream(LParam));
  Application.ProcessMessages;
  Sleep(2000);
end;

end.

...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511891
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С такой добавкой, а то не дописал - некрасиво, что не освобождается входящий стрим:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TForm1.UMIncomingStream(var Message: TMessage);
var
  S: TStream;
begin
  with Message do
    S := TStream(LParam);
  Memo1.Lines.LoadFromStream(S);
  S.Free;
  Application.ProcessMessages;
  Sleep(2000);
end;
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511936
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schi,

все, спасибо тебе большое - разобрался.

В случае с передачей массивов байтов ошибка была в том, что
Код: pascal
1.
2.
3.
  msg.wParam:= FArrStreamRec[0].ContainerType;
  //<skiped>
  SendMessage(Form1.Handle,WM_ADDSTREAMPARAM_MSG,0,DWORD(@FArrStreamRec[0]));


передавался 0, а не значение msg.wParam

Переделал на твой вариант, тоже все зафурычило, только кода меньше

Еще раз спасибо за познавательный код
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511937
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
приаттачу проект для идущих следом :)
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39511947
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schi,

Код: pascal
1.
2.
          MS.SetSize(FS.Size); // - чтобы что?
          MS.CopyFrom(FS, FS.Size);
...
Рейтинг: 0 / 0
Lazarus: передача blob, как параметра, внутрь и наружу TThread
    #39512032
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДschi,

Код: pascal
1.
2.
          MS.SetSize(FS.Size); // - чтобы что?
          MS.CopyFrom(FS, FS.Size);



Чтобы ты желтым выделил
(Привычка у меня осталась при работе с TMemoryStream задавать ему размер)
...
Рейтинг: 0 / 0
39 сообщений из 39, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lazarus: передача blob, как параметра, внутрь и наружу TThread
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]