Solved

How to force listening to buttonclick

Posted on 2014-02-24
12
276 Views
Last Modified: 2014-02-25
Hi,

In my application I do some fast processing. When the processing starts I want to be able to pause it.
For this purpose I have added a pause-button to the form. The only thing is, that when I press the button it doesn't react immediately. Sometimes I have to press it multiple times before it works. Meanwhile processing takes on.
Is there a way to make sure that the buttonclick will always be noticed and processing of the job is paused immediately?
0
Comment
Question by:Delphiwizard
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 2
  • +1
12 Comments
 
LVL 24

Expert Comment

by:jimyX
ID: 39882360
It depends on what you are doing, and what easy changes to be made to catch the button OnClick.

From top of my mind i can say use "Application.ProcessMessages" to process the button's code. But you need to use with care as it enforces processing all the queued messages.
0
 

Author Comment

by:Delphiwizard
ID: 39882605
I'll try to use it and see what happens.
0
 
LVL 27

Assisted Solution

by:Sinisa Vuk
Sinisa Vuk earned 100 total points
ID: 39882972
you can use threaded job to accomplish this. (Like BMThread). Thread will not stop your app and it can be easily stopped/paused.
0
[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

 
LVL 38

Accepted Solution

by:
Geert Gruwez earned 400 total points
ID: 39884862
here is a sample on how to use threading with a slow frontend
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/A_6613.html

to add pausing and resuming you need access to thread instance.
changing the procedure into a function solves that
function LoadData(obj: TObject; DataLoaded: TDataLoadedProc): TLoadDataThread;
begin
  Result := nil;
  if not mLoadDataThreadRunning then
  begin
    mLoadDataThreadRunning := True;
    Result := TLoadDataThread.Create(Obj, DataLoaded);
  end;
end;

Open in new window


off course you need to save the result of that function in your form instance
  TfrmEEThreads = class(TForm)
  ... 
  private
    fLoadingThread: TThread;
  end;

procedure TfrmEEThreads.btnShowDataClick(Sender: TObject);
begin
  // Call procedure and pass grid to load and proc to load the grid
  fLoadingData := LoadData(sgData, ShowData);
end;

Open in new window

the button would simply do pause/resume the thread
procedure TfrmEEThreads.btnPause(Sender: TObject);
begin
  if (fLoadingData <> nil) then 
    fLoadingData.Pause;
end;

procedure TfrmEEThreads.btnResume(Sender: TObject);
begin
  if (fLoadingData <> nil) then 
    fLoadingData.Resume;
end;

Open in new window

0
 

Author Closing Comment

by:Delphiwizard
ID: 39885000
Thank you all for the support.
I'll went for the approach suggested by Geert Gruwez. The posted article is great Geert.
0
 

Author Comment

by:Delphiwizard
ID: 39885141
@Geert Gruwez:
Using your example: I've tried to change the procedure into a function, but I get an error.
[DCC Error] uEELoadData.pas(35): E2065 Unsatisfied forward or external declaration: 'TLoadDataThread.LoadData'

Can you point me in the right direction?

unit uEELoadData;

interface

uses Classes;

const
  WaitSleep = 500;

type
  TDataLoadedProc = procedure (obj: TObject; List: TStrings) of object;
  TDataProgressProc = procedure (obj: TObject; ProcentDone: integer) of object;

implementation

uses SysUtils;

var
  mLoadDataThreadRunning: boolean;

type
  TLoadDataThread = class(TThread)
  private
    fDataLoaded: TDataLoadedProc;
    fDataProgress: TDataProgressProc;
    fObj: TObject;
    fList: TStrings;
    fProcentDone: integer;
    procedure DoDataLoaded;
    procedure DoProgress;
    function LoadData(obj: TObject; DataLoaded: TDataLoadedProc; DataProgress: TDataProgressProc): TLoadDataThread;
  protected
    procedure ReportProgress(ProcentDone: Integer);
    procedure Execute; override;
    property List: TStrings read fList;
  public
    constructor Create(Obj: TObject; DataLoaded: TDataLoadedProc; DataProgress: TDataProgressProc); reintroduce; virtual;
    destructor Destroy; override;
  end;

{ TLoadDataThread }

constructor TLoadDataThread.Create(Obj: TObject; DataLoaded: TDataLoadedProc; DataProgress: TDataProgressProc);
begin
  // Create thread not suspended
  inherited Create(False);
  // When finished, autofree
  FreeOnTerminate := True;
  // remember parameters
  fObj := Obj;
  fDataLoaded := DataLoaded;
  fDataProgress := DataProgress;
  fList := TStringList.Create;
end;

destructor TLoadDataThread.Destroy;
begin
  fList.Free;
  inherited Destroy;
end;

procedure TLoadDataThread.Execute;
const
  DataRows = 10;
  DataCols = 5;
var I, J: Integer;
  temp: string;
begin
  // Create the data
  List.Values['ROWS'] := IntToStr(DataRows +1);
  List.Values['COLS'] := IntToStr(DataCols +1);
  for I := 1 to DataRows +1 do
    for J := 1 to DataCols +1 do
    begin
      temp := '';
      if (J = 1) and (I > 1) then
        temp := Format('Row %d', [I-1])
      else if (I = 1) and (J > 1) then
        temp := Format('Column %d', [J-1])
      else if (J > 1) and (I > 1) then
        Temp := Format('Data %d_%d', [I-1, J-1]);
      List.Values[Format('%d_%d', [I, J])] := Temp;
      ReportProgress(Trunc(((I-1) * (DataCols+1) + J-1) / ((DataRows+1) * (DataCols+1))*100));
      Sleep(WaitSleep);
    end;
  ReportProgress(100);
  // Call the show procedure with the obj to show the created data in
  Synchronize(DoDataLoaded);
end;

procedure TLoadDataThread.ReportProgress(ProcentDone: Integer);
begin
  fProcentDone := ProcentDone;
  Synchronize(DoProgress);
end;

procedure TLoadDataThread.DoDataLoaded;
begin
  // Make sure we have all items assigned
  if Assigned(fDataLoaded) and Assigned(fObj) then
    fDataLoaded(fObj, fList);

  // clear the flag to stop a second thread
  mLoadDataThreadRunning := False;
end;

procedure TLoadDataThread.DoProgress;
begin
  if Assigned(fDataProgress) then
    fDataProgress(fObj, fProcentDone);
end;

function LoadData(obj: TObject; DataLoaded: TDataLoadedProc; DataProgress: TDataProgressProc): TLoadDataThread;
begin
  Result := nil;
  if not mLoadDataThreadRunning then
  begin
    mLoadDataThreadRunning := True;
    Result := TLoadDataThread.Create(Obj, DataLoaded, DataProgress);
  end;
end;

initialization
  mLoadDataThreadRunning := False;

end.

Open in new window

0
 
LVL 27

Expert Comment

by:Sinisa Vuk
ID: 39885157
As I can see - you must create thread as suspended:
inherited Create(False);

Open in new window


Later - after you call function and it returns thread - do call Resume.
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 39885173
i see, you used 2 articles, the progress and the loaddata ... :)

 you've made a method function of an ordinary function
the loaddata is not part of the Thread class

the mainform uses the TThread ancestor class for resume and pause

the ordinary function will create a thread on the fly
> doesn't really matter if it's started immediately

the one thing still needed is cleanup
the thread should still call a finishing routine when finished to reset the variable for the thread to nil
or you'll get AV's here and there

hmmm, it's been a while since i worked with this code...
i'll try and create a sample with cleanup and multiple threads
0
 

Author Comment

by:Delphiwizard
ID: 39885236
That would be great. :-)
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 39885288
well ... here the sample is
what the threads do is rather trivial in this sample ... count to 100 and sleep a little

the simulation
> start 2 threads
> when they have both finished, start a 3rd thread
> when that 3rd thread is finished optionally start the first 2 again
and so on ...

ooo ... crap, no delphi dproj files allowed.
i'll add an attention for the mods :)

here is the zipped project:
prjEEThreads.zip
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 39885308
change the last line in the main unit to take the checkbox into account ... :)

  if Task3Done and chkRepeatSimul.Checked and (fThreadTask1 = nil) and  (fThreadTask2 = nil) then
    btnStartSimul.Click;
end;

end.

Open in new window

0
 

Author Comment

by:Delphiwizard
ID: 39886187
Hi Geert,

That is some great simulation, thank you...
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Suggested Courses
Course of the Month6 days, 11 hours left to enroll

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question