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

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

Как сделать чтобы форма реагировала во время работы потоков. [D7, WinXP]


Страницы:   1 2 3 4

Kolan ©   (2005-05-27 10:09:00) 

Здравствуйте,
 Разбираюсь с потоками, нашел статью:
http://www.realcoding.net/article/view/158
Сделал пример где два потока, один включает флажок CheckBox'а другой выключает.
Если я всё правильно понял, то потоки должны работать себе и работать а форма нормально реагировать на все события.

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

Вот код потока:

type
 TMyThread1 = class(TThread)
 private
    { Private declarations }
 protected
   procedure DoWork;
   procedure Execute; override;
 end;


procedure TMyThread1.Execute;
begin
while not Terminated do
 Synchronize(DoWork);
end;

procedure TMyThread1.DoWork;
begin
 Form1.CheckBox.Checked := True;
end;

Ну соотвественно второй
Form1.CheckBox.Checked := False;

Код главного юнита.

var
 Form1: TForm1;
  T1: TMyThread1;
  T2: TMyThread2;


На форме одна кнопка:
procedure TForm1.StopButtonClick(Sender: TObject);
begin
 if StopButton.Caption = 'Ñòîï' then
 begin
   {Ïðåðûâàåì îáà ïðîöåññà}
   T1.Terminate;
   T2.Terminate;
   StopButton.Caption := 'Ñòàðò';
 end
 else
 begin
   {Ñîçäàåì è ñðàçó çàïóñêàåì äâà ïðîöåññà}
   T1 := TMyThread1.Create(False);
   T2 := TMyThread2.Create(False);

   StopButton.Caption := 'Ñòîï';
 end;
end;


Что я нетак понял или сделал?


Anatoly Podgoretsky   (2005-05-27 14:21:00) [21]

Digitman ©   (27.05.05 14:10) [39]
А это уже означает агрегатные, они к тому же еще и чрезвычайно медленные на современных процессорах. Хорощо что Борланд не купился на них в своем компиляторе.


Digitman   (2005-05-27 14:21:00) [22]


> Alex Konshin ©   (27.05.05 14:14) [40]


> значения в регистрах должны как-то оказаться


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


Alex Konshin   (2005-05-27 14:14:00) [23]

Digitman ©   (27.05.05 14:10) [39]
> Alex Konshin ©   (27.05.05 14:04) [38]
ну эт ты загнул)
прерваны они, конечно, м.б., но только не одиночные (т.е. если используется REPХХ-префикс)

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


Digitman   (2005-05-27 14:10:00) [24]


> Alex Konshin ©   (27.05.05 14:04) [38]


ну эт ты загнул)

прерваны они, конечно, м.б., но только не одиночные (т.е. если используется REPХХ-префикс)


Alex Konshin   (2005-05-27 14:04:00) [25]

Цепочечные операции точно неатомарные, потому что они могут быть прерваны.


Digitman   (2005-05-27 14:04:00) [26]


> В списке также отсутствуют строковые команда MOVS/STOS/LODS,
> которые впринципе не атомарны


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


Defunct   (2005-05-27 13:56:00) [27]

Alex Konshin ©   (27.05.05 13:52) [33]

> Да, mov атомарный, но нужно пояснить

А как же быть с Movs? Тоже атомарный?

Интересует что же происходит с сигналом Lock# при отработке строковых операций.


Германн   (2005-05-27 13:55:00) [28]

2Игорь Шевченко ©   (27.05.05 11:29) [13]
>Архангельский маст дай.

А это не Архангельский! Это тот же Карих Николай, которого Digitman терпеть не может. Странно, что последний в данном случае промолчал. :)


Суслик   (2005-05-27 13:55:00) [29]

Еще неатомарная операция: присваивание константы значению типа int64


Alex Konshin   (2005-05-27 13:52:00) [30]

О, пока писал, тут уже понаписали.

Digitman ©   (27.05.05 13:07) [29]
Да, mov атомарный, но нужно пояснить, что из этого не следует, что любое присваивание в  Delphi - атомарно, потому значение в регистре должно еще как-то оказаться. Простой пример: два переменные и мы присваиваем значение одной переменной другой. Это - неатомарная операция. Вот присваивание константы - атомарная операция.


Alex Konshin   (2005-05-27 13:45:00) [31]

Alexander Panov ©   (27.05.05 11:45) [16]
Несколько важныхзамечаний по примеру:

1. Пока не буду вдаваться в обсуждение нужно ли защищать изменение FInterval. Просто хочу указать, что если уж нужно, то довольно часто можно обойтись вызовом одной из из функций Interlocked* (например, InterlockedExchange, InterlockedIncrement) или же коммандой в ассемблере с модификатором lock.

2.Применять критические секции, как и другие средства блокировки нужно обдуманно и обоснованно. В противном случае можешь иметь проблемы с deadlock. Особенно осторожно нужно быть в случае вложенных критических секции (с несколькими критическими секциями). В этом случае deadlock довольно просто получить, если в разных последовательностях исполнения вложение происходит в разном порядке. Вложенные критические секции могут получится, например, в результате прямого или косвенного вызова методов, которые используют другую критическую секцию. Еще обратите внимание, что под "критические секции" в этом пункте я подразумеваю не только TRtlCriticalSection и его производные, но и семафоры и т.п., т.е. все, что может блокировать исполнение.

3. Когда нужно применять критические секции или другие способы синхронизации доступа? Очень распространенная ошибка начинающих (и не только) в том, что они считают, что защиты требуют только глобальные переменные. Другое заблуждение мы только что видели: то, что не нужно защищать приватные переменные. Третье заблуждение мы тоже только что видели: то, что нужно защищать только тогда, когда изменяется более одной переменной. На самом же деле нужно защищать тогда и только тогда, когда:
- Существует возможность доступа к этому ресурсу несколькоми потоками(при этом абсолютно не играет роли, что этот ресурс - приватная переменная какого-то объекта, пусть даже наследника TThread).
- Операция с этим ресурсом неатомарнаяи изменение ресурса  зависит от его текущего состояния/значения. Например, если вы читаете некую переменную, сравниваете ее с чем-нибудь и в зависимости от результата можете изменить ее значение, то эта операция неатомарная (кстати, ее часто можно заменить на одну из атомарных функций Interlocked*). Если вы даже просто прибавляете к некому полю некое число, то это тоже неатомарная операция (опять-таки, это можно сделать с помощью атомарной InterlockedIncrement).


Defunct   (2005-05-27 13:44:00) [32]

Digitman ©   (27.05.05 13:07) [29]

> мы видим, что MOV среди инструкций, к которым применим этот префикс, отсутствует, и это дает повод говорить об атомарности инструкции по дифолту

Нет, такого повода, это нам не дает. В списке также отсутствуют строковые команда MOVS/STOS/LODS, которые впринципе не атомарны.


-=XP=-   (2005-05-27 13:32:00) [33]

2 Digitman

 Спасибо


Digitman   (2005-05-27 13:07:00) [34]


> Является ли операция (сохранение, например, значения из
> регистра процессора в ячейку памяти) атомарной по сути своей?


за ответом на вопрос заглянем в мануал Интела

смотрим, что Интел говорит о префиксе LOCK, который собственно и делает инструкцию атомарной

Causes the processor’s LOCK# signal to be asserted during execution of the accompanying
instruction (turns the instruction into an atomic instruction). In a multiprocessor environment,
the LOCK# signal insures that the processor has exclusive use of any shared memory while the
signal is asserted.
Note that in later IA-32 processors (including the Pentium 4, Intel Xeon, and P6 family proces-sors),
locking may occur without the LOCK# signal being asserted. See IA-32 Architecture
Compatibility below.
The LOCK prefix can be prepended only to the following instructions and only to those forms
of the instructions where the destination operand is a memory operand: ADD, ADC, AND,
BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR,
XADD, and XCHG. If the LOCK prefix is used with one of these instructions and the source
operand is a memory operand, an undefined opcode exception (#UD) may be generated. An
undefined opcode exception will also be generated if the LOCK prefix is used with any instruc-tion
not in the above list. The XCHG instruction always asserts the LOCK# signal regardless of
the presence or absence of the LOCK prefix.
The LOCK prefix is typically used with the BTS instruction to perform a read-modify-write
operation on a memory location in shared memory environment.
The integrity of the LOCK prefix is not affected by the alignment of the memory field. Memory
locking is observed for arbitrarily misaligned fields.

мы видим, что MOV среди инструкций, к которым применим этот префикс, отсутствует, и это дает повод говорить об атомарности инструкции по дифолту


TUser   (2005-05-27 12:59:00) [35]

И все-таки что неправильно в [11]?


Игорь Шевченко   (2005-05-27 12:57:00) [36]


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


В ходе записи - не может. В ходе чтения, а конкретно в методе _Sleep - может, теоретически. То есть, критическая секция здесь ни к чему.


-=XP=-   (2005-05-27 12:46:00) [37]

В таком случае, разумно и чтение в методе _Sleep защитить критической секцией ?

Вот по этому поводу и вопрос: Нужно ли чтение/запись переменной типа Cardinal (32 бита) защищать критической секцией?

То-есть, может ли поток быть приостановлен (для передачи процессора в ведение другого потока) в ходевыполнения чтения/записи этой переменной? Или, если это многопроцессорная система, то может ли ячейка памяти читаться одним процессором в тот же момент, когда другой процессор производит в нее запись? Защищена ли память от таких одновременных операций (то-есть, один процессор пишет старший байт 32-битной переменной, а другой читает младший байт)? Является ли операция (сохранение, например, значения из регистра процессора в ячейку памяти) атомарной по сути своей?


Игорь Шевченко   (2005-05-27 12:33:00) [38]

-=XP=- ©   (27.05.05 12:28) [23]


> Про помощи метода SetInterval().


Угу, сообразил.

В таком случае, разумно и чтение в методе _Sleep защитить критической секцией ?


Kolan   (2005-05-27 12:32:00) [39]


> Erik1 ©   (27.05.05 12:16) [20]

Ну дык ктож знал. Чё первое попалось то и прочел. :).


-=XP=-   (2005-05-27 12:28:00) [40]

Это как ? Переменная же является приватной для каждого потока ?

Про помощи метода SetInterval().

Речь идет о необходимости критической секции внутри методов SetInterval/GetInterval.


Страницы:   1 2 3 4

Наверх

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