roots fish die

ikan makan plankton ikan hidup di air ikan butuh air

Rabu, 09 Desember 2009

Memanfaatkan Thread untuk proses yang lama

Kadangkala aplikasi kita mengerjakan sesuatu yang membutuhkan hasil yang lumayan lama. Akibatnya aplikasi kita kelihatan hang, dan pengguna aplikasi jadi merasa terganggu.
Saya pernah mengalami hal itu, saat sedang query yang cukup kompleks ke server. Atau ada juga aplikasi yang sedang berkomunikasi ke server melalui internet, menunggu respon server yang lumayan lama. Sehingga aplikasi kita kelihatan hang.

Untuk mengatasi itu saya mengakalinya dengan membuat obyek Thread di memory. Dan pekerjaan yang sering membutuhkan waktu tersebut diberikan kepadanya. Saya berikan contoh bagaimana saya memanfaatkan Thread pada Delphi. Namun ini juga dapat diterapkan pada Lazarus/FreePascal dengan sedikit perubahan.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ZAbstractRODataset, ZAbstractDataset, ZDataset, ZConnection,
  StdCtrls, Grids, DBGrids, ExtCtrls;

type
  TExec = class(TThread) // kelas turunan TThread
  protected
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    ZConnection1: TZConnection;
    ZQuery1: TZQuery;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Memo1: TMemo;
    Panel1: TPanel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    Exec: TExec;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  PesanTunggu;

{$R *.dfm}

procedure TExec.Execute;
begin
  // mencoba query ke server melalui sebuah thread
  with Form1 do begin
    if zquery1.Active then zquery1.close;
    ZQuery1.SQL:=Memo1.Lines;
    FormTunggu.Visible:=true;
    zquery1.Open;
    FormTunggu.Visible:=false;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Exec:=TExec.Create(False); // disini procedure TExec.Execute akan dieksekusi
  Exec.FreeOnTerminate:=true; // memberitahu obyek Exec agar menghapus instansi dari memory jika query selesai
end;

end.
 
 
 
 
 
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, Buttons, Grids, DBGrids, DB, ADODB;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. ADOConnection1: TADOConnection;
  12. ADOQuery1: TADOQuery;
  13. ADOQuery2: TADOQuery;
  14. DataSource1: TDataSource;
  15. DataSource2: TDataSource;
  16. DBGrid1: TDBGrid;
  17. DBGrid2: TDBGrid;
  18. BitBtn1: TBitBtn;
  19. Button1: TButton;
  20. procedure BitBtn1Click(Sender: TObject);
  21. procedure Button1Click(Sender: TObject);
  22. private
  23. { Private declarations }
  24. public
  25. { Public declarations }
  26. end;
  27.  
  28. //Thread class declaration - very simple
  29. TQThread = class(TThread)
  30. private
  31. FQuery: TADOQuery;
  32. protected
  33. procedure Execute; override;
  34. public
  35. constructor Create(Query: TADOQuery);
  36. end;
  37. var
  38. Form1: TForm1;
  39.  
  40. implementation
  41.  
  42. {$R *.dfm}
  43.  
  44. uses DateUtils;
  45.  
  46. constructor TQThread.Create(Query: TadoQuery);
  47. begin
  48. inherited Create(True); //Create thread in a suspendend state so we can prepare vars
  49. FQuery := Query; //Set up local query var to be executed.
  50. FreeOnTerminate := True; //Free thread when finished executing
  51. Resume;
  52. end;
  53.  
  54. procedure TQThread.Execute;
  55. begin
  56. FQuery.DisableControls;
  57. FQuery.Open; //Perform the query
  58. FQuery.EnableControls;
  59. end;
  60.  
  61. procedure TForm1.BitBtn1Click(Sender: TObject);
  62. begin
  63. // ujicoba menggunakan query dibuka seperti biasa (sequential)
  64. ADOQuery1.Open;
  65. ADOQuery2.Open;
  66. end;
  67.  
  68. procedure TForm1.Button1Click(Sender: TObject);
  69. begin
  70. // ujicoba menggunakan thread
  71. TQThread.Create(ADOQuery1);
  72. TQThread.Create(ADOQuery2);
  73. end;
  74.  
  75. end.