Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  17:55[Войти] | [Зарегистрироваться]
Ответ на вопрос № 70676

15-05-2009 10:03
Помогите решить проблему.
Есть 2-е процедуры.
К примеру по нажатию кнопки 1 запускается процедура 1.
Процедура выполняется долго к примеру 10 секунд.
Если на 5-й секунде нажатием кнопки 2 запустить процедуру 2,
процедура 1 останавливается, выполняется процедура 2,
после чего продолжает выполняться процедура 1.

Что можно придумать, не перенося процедуры в потоки,
чтобы при нажатии кнопки 2, процедура 1 доработала до конца
и только после этого исполнилась процедура 2?

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

Простейший пример ниже.


procedure TForm1.Button5Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to 100 do
  begin
    sleep(100);
    Application.ProcessMessages;
    progressbar1.Position:=i;
  end;
end;

procedure TForm1.Button6Click(Sender: TObject);
var i:integer;
begin
  for i:=0 to 100 do
  begin
    sleep(100);
    Application.ProcessMessages;
    progressbar2.Position:=i;
  end;
end;

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

18-05-2009 05:37 | Сообщение от автора вопроса
Всем спасибо.
Вопрос решен.
Принято решение организовать список(стек) задач,
с последовательным исполнением задач из списка.
Отдельная благодарность NS за развернутый ответ.

16-05-2009 00:57
Если требуется последовательное исполнение, приходит мысль сделать ОЧЕРЕДЬ, куда записывать элементы по нажатию кнопок и исполнять нужные методы, извлекая эти элементы оттуда.

15-05-2009 22:08
Следуя примеру предыдущего оратора, должен заметить, что в моём примере тоже не всё гладко :)) Не хватает одной строки в методе ApplicationEvents1Idle где-нибудь между if ... begin ... end нужно добавить Done:= false

Хочу так-же предупредить, что я вряд-ли стал бы писать такое на трезвую голову :)

15-05-2009 14:49
Прошу прощения, в моём сообщении от 15-05-2009 11:47 содержатся неточности.
Во-первых, использование простых флагов вполне корректно в пределах одной нити.
Во-вторых, приведенный мной код проигнорирует, а не отложит запуск второй процедуры при выполнении первой.
Но есть и случайный плюс: будет заблокирован случайный повторный запуск уже запущенной процедуры.

15-05-2009 11:47
Ну тогда можно флагами. Не уверен насчет абсолютной корректности такого простого подхода, но если события не очень частые, то сбоев почти не будет. Для абсолютной уверенности можно воспользоваться системными способами синхронизации.

var MyFlagOn:boolean=false; 

procedure TForm1.Button5Click(Sender: TObject);
var i:integer;
begin
if MyFlagOn then exit else MyFlagOn:=true; 
  for i:=0 to 100 do
  begin
    sleep(100);
    Application.ProcessMessages;
    progressbar1.Position:=i;
  end;
MyFlagOn:=false; 
end;

procedure TForm1.Button6Click(Sender: TObject);
var i:integer;
begin
if MyFlagOn then exit else MyFlagOn:=true; 
  for i:=0 to 100 do
  begin
    sleep(100);
    Application.ProcessMessages;
    progressbar2.Position:=i;
  end;
MyFlagOn:=false; 
end;


15-05-2009 11:44

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ApplicationEvents1: TApplicationEvents;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
  private
    { Private declarations }
    FList: TList;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function CreateFiber(dwStackSize: DWORD; lpStartAddress: TFNFiberStartRoutine;
  lpParameter: Pointer): Pointer; stdcall; external kernel32 name 'CreateFiber';
function ConvertFiberToThread(): BOOL; stdcall;
              external kernel32 name 'ConvertFiberToThread';
function ConvertThreadToFiber(lpParameter: Pointer): Pointer; stdcall;
              external kernel32 name 'ConvertThreadToFiber';

var
  MainFiber, Fiber: pointer;

procedure Proc1();
var
  n: integer;
begin
  for n:= 0 to 100 do
  begin
    Sleep(100);
    if GetQueueStatus(QS_ALLINPUT) <> 0 then
      SwitchToFiber(MainFiber);
  end;
end;

procedure Proc2();
var
  n: integer;
begin
  for n:= 0 to 100 do
  begin
    Sleep(100);
    if GetQueueStatus(QS_ALLINPUT) <> 0 then
      SwitchToFiber(MainFiber);
  end;
end;

procedure FiberFunc(List: TList); stdcall;
var
  P: TProcedure;
begin
  while true do
  begin
    if List.Count <> 0 then
    begin
      P:= List[0];
      if @P <> nil then P();
      List.Delete(0);
    end else
      SwitchToFiber(MainFiber);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FList:= TList.Create;
  MainFiber:= ConvertThreadToFiber(nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FList.Add(Addr(Proc1));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FList.Add(Addr(Proc2));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Fiber <> nil then DeleteFiber(Fiber);
  ConvertFiberToThread();
  FList.Free;
end;

procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
  var Done: Boolean);
begin
  if FList.Count <> 0 then
  begin
    if Fiber = nil then Fiber:= CreateFiber($100000, @FiberFunc, FList);
    SwitchToFiber(Fiber);
  end;
end;

end.



Это конечно извращение, но и задача у Вас не лучше :)

15-05-2009 11:04 | Комментарий к предыдущим ответам
Не все так просто.
Форма должна оставаться активной.
Процедуры в реальной задаче запускаются 3-мя способами: Кнопка/Таймер/По факту коннекта сокета.
Эти события нельзя блокировать, нужно просто выполнять процедуры последовательно и до конца.

15-05-2009 10:53
Первое что приходит на ум - убрать из обеих процедур ProcessMessages.

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Два кольца, два конца, посередине гвоздик.
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования