Penulis: Zou Fei
Email: [email protected]
Beranda: http://www.atechsoft.com/people/zouf/ Dalam proses menggunakan Delphi, Anda pasti akan menemui banyak masalah aneh, dan dokumentasi Delphi juga sangat sedikit, jadi saya hanya bisa merangkumnya sendiri secara perlahan , jadi ada (Karena hanya detail yang tersebar, saya tidak menghabiskan banyak tenaga untuk menulisnya, mungkin agak berantakan, tapi harus bisa dimengerti ;-)). Jika: 1. Jika Anda memiliki solusi yang lebih baik untuk masalah berikut, silakan beri tahu saya dan teman saya di csdn. 2. Jika Anda memiliki pertanyaan lain, harap cantumkan masalah dan jawaban Anda dan beri tahu saya dan teman saya di csdn. Komunikasi menciptakan segalanya!
Teks: Q: Jika Formulir yang dibuat di Delphi DLL adalah ShowModal di Exe, akan muncul dua ikon di taskbar. Bagaimana cara mengatasi masalah ini? A: Berikut ini adalah metode umum menempatkan Formulir di DLL: DLL: function ShowFrm: TModalResult; stdcall;beginForm1 := TForm1.Create(tryForm1.ShowModal; fungsi ShowFrm: TModalResult; 'TestDLL.dll';…begin…ShowFrm;…end. Formulir di DLL yang dibuat dengan cara ini akan menampilkan Ikon lain dengan aplikasi utama. Alasannya adalah aplikasi lain akan dibuat untuk DLL di Delphi Aplikasi akan menampilkan ikon taskbar. Solusi: Masukkan Aplikasi EXE utama ke dalam DLL di aplikasi utama, sebagai berikut: DLL: function ShowFrm(app: TApplication): TModalResult;stdcall;varoldApp: TApplication;beginoldApp := Application;Application := app;Form1 : = TForm1.Create(Nil);tryForm1.ShowModal;finallyForm1.Free;end;Aplikasi := oldApp;end;EXE Utama: function ShowFrm(app: TApplication): TModalResult; stdcall; external 'TestDLL.dll';…begin…ShowFrm(Application);…end masih ada beberapa perbedaan, lihat kode di Forms.pas: konstruktor TApplication.Create(AOwner: TComponent);begin…jika bukan IsLibrary maka CreateHandle;…end;Dapat diketahui bahwa Aplikasi di DLL tidak memiliki Handle, sehingga pemrosesan loop pesan tidak akan dilakukan, yang juga benar. Q: Masalah sering terjadi dengan DLL di Delphi! J: Alasan mengapa masalah ini terjadi adalah karena mekanisme manajemen memori Delphi sendiri. Misalnya: Buat objek di DLL: x := TClass.Create(Application); Saat ini, Delphi akan secara otomatis Mengosongkan Ruang alamat mungkin telah kedaluwarsa (sistem operasi berbeda akan berbeda), sehingga operasi pelepasan x akan terjadi. menyebabkan pengecualian. Contoh lain: Buat objek di EXE, dan masukkan DLL sebagai variabel lokal di DLL. Ketika DLL dimusnahkan, Delphi akan secara otomatis melepaskan semua variabel yang berada di luar cakupan, jadi jika Anda menggunakan ini di EXE lagi objek, sebuah pengecualian akan dilempar. Secara umum, masalah ini disebabkan oleh mekanisme manajemen memori dari kompiler Delphi "pintar" dan mekanisme penambahan/pembongkaran DLL pada Windows, yang menyebabkan konflik akses memori pada DLL dan EXE. Solusi: (Sebagian besar masalah dapat dihindari selama Anda mengikuti prinsip-prinsip berikut) 1. Antara DLL dan EXE, cobalah untuk tidak menggunakan mekanisme manajemen memori otomatis Delphi. Pemrogram bertanggung jawab atas siklus hidup objek. Misalnya: untuk x := TClass.Create(Application); TClass.Create(nil); Dengan cara ini, Aplikasi tidak akan lagi Membebaskannya. Tentu saja programmer harus membebaskannya sendiri. 2. Cobalah untuk menghindari petunjuk berbeda yang menunjuk ke objek yang sama antara DLL dan EXE. Misalnya, di DLL, x menunjuk ke objek TClass, dan di EXE, y menunjuk ke objek TClass. Dengan cara ini, pelepasan memori di kedua sisi akan menyebabkan memori di sisi lain menjadi tidak valid. 3. Lainnya... Q: Thread yang melakukan tugas berkala perlu dijeda sejenak dan kemudian terus berjalan. Namun bagaimana jika thread perlu dihentikan saat ini (misalnya proses telah berakhir)? A: Solusi 1: Lakukan perulangan berkala melalui Sleep di thread. (Jika thread dijeda melalui mode Tidur, thread tidak dapat dihidupkan kembali melalui Resume dan metode lainnya.) Akhiri thread melalui KillThread. Ini adalah metode paling sederhana, namun terlalu kasar dan dapat menyebabkan masalah (KillThread adalah API yang tidak disarankan untuk Windows) Solusi 2: Tangguhkan thread, lewati pengatur waktu di luar thread, dan Lanjutkan sesekali. Kodenya adalah sebagai berikut: // ThreadPRocedure Execute;begin while not Dihentikan dobegin... // Memproses kode Suspend;end;end;// Outside // Timer procedure OnTimer(Sender: Tobject);beginthd.Resume;end;// Untuk mengakhiri thread Place...thd.Resume;thd.Terminate;thd.WaitFor; Umumnya, setelah mengakhiri thread, Anda harus menggunakan WaitFor untuk mengonfirmasi bahwa thread tersebut benar-benar telah berakhir. ...Masalah: Kopling antara ulir dan bagian luar terlalu kuat, dan bahkan siklus pengoperasian ulir harus ditentukan melalui pengatur waktu eksternal. Solusi ketiga (ini adalah cara terbaik yang saya pikirkan): Jeda di thread melalui semaphore. // ThreadTMyThread = class(TThread)private Event: TEvent;prosedur yang dilindungi Jalankan; override;konstruktor publik Buat(loginInfo: TLoginInfo kelebihan beban; prosedur override; TLoginInfo);mulai Acara := TEvent.Create(nihil, Benar, Benar, 'EventName');end;destructor TMyThread.Destroy;begin Event.Free; diwariskan;end;prosedur TMyThread.Execute;begin diwarisi sementara tidak Dihentikan, lakukan mulai // ... Event.ResetEvent; end;end;procedure TMyThread.SetEvent;begin Event.SetEvent;end;Untuk program yang perlu menginterupsi thread, kode berikut saja sudah cukup: mulai …thd.Terminate;thd.SetEvent;thd.WaitFor;…end;