![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создание двух потоков [D5, Win2k]
tiam © (2002-12-24 14:49:00)Добрый день.
Кто может привести краткий и понятный код, либо дать ссылку, как пример работы двух потоков, например, в одном идут вычисления и вывод на битмап, а в другом, в это же время ввод данных в едит.
Те примеры, что видел, не очень наглядны, слишком запутаны, как, например, этот: http://delphi.mastak.ru/articles/panov/index.html.
Стандартный демопример из Делфи тоже не слишком нагляден.
Спасибо.
Alex Konshin (2002-12-25 20:03:00) [1]2 Александр Спелицин:
Use this routine or a TThread object to spawn separate threads of execution. BeginThread spawns a new thread of execution and sets the global IsMultiThread variable, thereby making the heap thread-safe.
ThreadFunc is the thread function. This is the code that executes in the new thread of execution. ThreadFunc should handle all of its own exceptions. However, because BeginThread sets up an execution frame, the system"s default exception handler will catch any exceptions that escape ThreadFunc.
Другими словами, она формирует фрейм для правильной обработки exception, и, что более важно, говорит менеджеру памяти, что приложение многопоточное.
Digitman (2002-12-25 17:15:00) [2]выполнение строки
Pb.Canvas.Draw(0, 0, workbmp);
должно быть синхронизировано с осн.потоком
1. сделай workbmp не лок.переменной , а полем класса потока
2. помести указ.строчку в тело какой-нибудь метода типа TMyThread.DoDraw
3. вместо
Pb.Canvas.Draw(0, 0, workbmp);
пиши
Synchronize(DoDraw);
кр.того не вздумай менять StringList в осн.потоке, пока он передан на обработку дополнительному параметром Source.
лучше передавай копию StringList"а
или придется переделывать оч.многое в Execute() и RunText()
ввод, кстати, здесь совершенно ни при чем.
часть проблем у тебя именно из-за того, что один поток пытается что-то писать в StringList, а другой (не зная об изменениях) - читать из него.
Polevi (2002-12-25 16:59:00) [3]надо формировать изображение в потоке, и посылать сообщение окну, в обработч которого рисовать его
tiam (2002-12-25 16:51:00) [4]в Execute следующее:
procedure tmythread.Execute;
begin
while (not Terminated) do // также пробовал и без этого условия
begin
RunText(form1.Memo1.Lines, form1.PaintBox1);
end;
end;
Сама процедура text - плывущий вверх текст, причем без строк:
while iterate do begin end; не выводит ничего на битмап.
procedure tmythread.Text(const SL: TStrings; const Pb: TPaintBox);
var i, w, y: integer;
Bmp, WorkBmp: TBitmap;
curpos, counter, maxcounter: integer;
cf: double;
function Iterate: boolean;
procedure PrepareBmp(const Source, Dest: TBitMap);
var x, y, mean, tmpx, tmpy: integer;
sb, db: PByteArray;
f, x1, y1, h, h0: double;
begin
h0 := Pb.Height;
h := Pb.Height;
f := 300;
result := counter<source.Height;
mean := (Source.Width - 1) div 2;
for y := 1 to Dest.Height - 1 do
begin
db := Dest.ScanLine[Dest.Height - y];
y1 := (y * counter + y * pb.height - h0 * pb.height - y + y * f - h0 * counter + h * f + h0 - h0 * f) / (-h0 + y);
tmpy := round(y1);
if (tmpy >= 0) and (tmpy < source.Height) then
begin
sb := Source.ScanLine[tmpy];
for x := 0 to Dest.Width - 1 do
begin
x1 := -(-y + h0 - h) * mean / (-h0 + y) - x * h / (-h0 + y);
tmpx := round(x1);
if (tmpx >= 0) and (tmpx < source.Width) then
begin
db[x * 2] := sb[2 * tmpx];
db[x * 2 + 1] := sb[2 * tmpx + 1];
end;
end;
end;
end;
end;
begin
inc(counter);
PatBlt(WorkBmp.Canvas.Handle, 0, 0, bmp.Width, bmp.Height, Blackness);
PrepareBmp(Bmp, WorkBmp);
Pb.Canvas.Draw(0, 0, workbmp);
dec(curpos);
end;
begin
counter := 0;
Bmp := TBitmap.Create;
Bmp.PixelFormat := pf16bit;
WorkBmp := TBitmap.Create;
with bmp do begin
width := Pb.Width;
Canvas.Font.Size := 18;
height := round(sl.Count * Canvas.Font.Size * 1.5) + 10 + pb.Height;
Canvas.Font.Name := "Arial";
Canvas.Font.Color := clwhite;
Canvas.Brush.Style := bsClear;
y := pb.Height;
PatBlt(Canvas.Handle, 0, 0, bmp.Width, bmp.Height, Blackness);
with bmp.canvas do
for i := 0 to sl.Count - 1 do
begin
w := TextWidth(sl[i]);
TextOut((bmp.Width - w) div 2, y, sl[i]);
y := y + (Font.Size * 3) div 2; ;
end;
curpos := Pb.Height - 2;
end;
WorkBmp.width := bmp.Width;
WorkBmp.Height := pb.Height;
WorkBmp.PixelFormat := pf16bit;
while iterate do
begin
end;
end;
Digitman (2002-12-25 16:42:00) [5]Приведи код Execute() !
tiam (2002-12-25 16:32:00) [6]Дело в том, что поток реагирует на движение мыши, даже если это не указано, то есть вывод на битмап останавливается, если пошевелить мышкой, например, а иногда и просто стопорится без видимых причин.
Как будто поток перестает выполняться.
А при повторном запуске может выполниться иначе(застрять в другом месте).
Как обрабатывается ввод, если не делаю синхронизацию?
Об этом я тоже спрашивал, никто не ответил.
Polevi (2002-12-25 16:31:00) [7]не упрямся, дай код, мы не будем его использовать в корыстных целях
Digitman (2002-12-25 16:28:00) [8]а что за клоунада с переодеваниями ? то <tiam> то <sel>...
вроде бы об одном и том же речь идет ..
или я ошибаюсь ?)
Digitman (2002-12-25 16:28:00) [9]а что за клоунада с переодеваниями ? то <team> то <sel>...
вроде бы об одном и том же речь идет ..
или я ошибаюсь ?)
Reindeer Moss Eater (2002-12-25 16:23:00) [10]SecondThread.Terminated := True;
Не останавливает поток. Всего лишь флаг Terminated устанавливается в True;
Внутри execute это надо проверять и выходить их метода.
tiam (2002-12-25 16:21:00) [11]приложение не закрывается все равно, хотя поток должен был разрушиться
Digitman (2002-12-25 16:19:00) [12]Ну и ? А что у тебя делается в Execute() ?
tiam (2002-12-25 16:12:00) [13]я пишу:
Secondthread:=TMythread.Create(true);
Secondthread.Priority:=tpLower;
Secondthread.Resume;
просто указывал выше
Digitman (2002-12-25 16:07:00) [14]
> Secondthread:=TMythread.Create(true);
Почему Create(true) ? Почему не Create(False) ? Где Resume в таком случае ?
> при нажатии любой клавиши в основном модуле я должен делать:
>
> Secondthread.free;
> application.terminate;
Да по барабану ! Хоть клавиша хоть не клавиша...
Суть одна и та же : если ты создал объект-поток вызовом конструктора, то обязан разрушить этот объект вызовом деструктора в ЛЮБОМ удобном месте программы и при ЛЮБОМ событии, но - ДО вызова "application.terminate"
Есть, правда, и другой, "скрытый" способ - заставить сам поток разрушить объект, создавший его. На то есть св-во FreeOnTerminate, установив которое (в любое время, пока поток еще работает) в True, ты тем самым указываешь потоку на необходимость самостоятельно вызвать деструктор своего управляющего объекта непосредственно перед завершением.
В таком случае для терминирования потока извне достаточно установить его св-во Terminated = True, все остальное поток сделает сам.
sel (2002-12-25 15:55:00) [15]Ну хорошо, напишу я так:
tmythread = class(TThread)
Secondthread:=TMythread.Create(true);
я так понял, что при нажатии любой клавиши в основном модуле я должен делать:
Secondthread.free;
application.terminate;
При этом на клавиши реакции нет.
Где я должен написать следующее и должен ли вообще:
Secondthread.FreeOnTerminate:=true;
Secondthread.Terminate;
Вывод на экран останавливается в разных состояниях при перезапуске программы, хотя должен пройти полностью.
Digitman (2002-12-25 15:26:00) [16]Ну при чем здесь stream и process ??? ну ведь имена идентификаторов в тексте программы должны же хоть как-то отражать их назначение и отношение к чему-либо ?
речь-то у тебя идет о кодовых потоках ! о thread"ах !
ну так и используй для этой цели "thread" ! а не "process" и не "stream" !! ... хоть "My" хоть не "My"))...
TMyThread = class(TThread) // декларация поточного класса
...
var
MyThread : TMyThread; // переменная, которая будет хранить адрес экз-ра поточного класса
...
MyThread := TMyThread.Create(...); // создаешь экземпляр поточного класса TMyThread и фиксируешь ссылку на него в соответствующей переменной MyThread
Что непонятно тут ?
tiam (2002-12-25 15:10:00) [17]Как я и создал:
tmystream = class(TThread);
myProcess:=TMystream.Create();
Вопрос в том, что такое MyThread
Polevi (2002-12-25 14:55:00) [18]:-))
Digitman (2002-12-25 14:55:00) [19]к тому же понятия stream и thread (не смотря на то, что и то и другое достаточно правильно называть "поток") - совершенно разные ! И по сути и по назначению !
stream ("поток") = поток данных
thread ("нить", "кодовый поток") = поток маш.инструкций (или - маш.кода), выполняемых центральным процессором (одним или более) в многозадачной ОС
Digitman (2002-12-25 14:49:00) [20]
> А что такое MyThread?
а что такое MyProcess ???
и что такое stream ???
и вообще - ты взялся за потоки (действительно - не самое простое дело !), а в Object Pascal "плаваешь")
Отвлекись от своих потоков - вопрос тебе на засыпку :
если имеется класс TMyClass с конструктором Create(), то как создать экземпляр класса, получив при этом его адрес и зафиксировав в некоей переменной ?