Menunjukkan berbagai cara untuk menggunakan utas di Delphi

Terlalu banyak pengguna Delphi membuat kesalahan dengan berpikir utas adalah semacam sihir yang akan meningkatkan kinerja aplikasi mereka. Sayangnya, ini jauh dari benar. Kesalahan terbesar #1 ketika mencoba mengimplementasikan utas adalah secara langsung mengakses kontrol visual aplikasi. Tetapi kontrol visual ini hanya dapat bekerja dalam konteks utas utama aplikasi. Menggunakan utas lain untuk memperbarui kontrol di antarmuka pengguna harus direncanakan dan diimplementasikan dengan sangat hati -hati. Dan dalam kebanyakan kasus, itu mungkin bukan solusi yang tepat untuk masalah sama sekali.
Sederhananya, kerangka kerja VCL Delphi tidak aman. Meskipun ada banyak cara untuk mengintegrasikan utas ke dalam UI Anda, tidak ada solusi satu ukuran untuk semua. Ini akan selalu bervariasi tergantung pada apa yang Anda coba capai. Sebagian besar waktu, orang ingin mencapai kinerja yang lebih baik (kecepatan). Tapi itu sangat jarang dilakukan dengan menggunakan utas. Sebaliknya, skenario yang paling umum di mana utas diintegrasikan ke dalam antarmuka pengguna adalah menjaga agar UI responsif selama tugas panjang.
Untuk ini, kami akan membayangkan aplikasi sederhana dengan hanya satu tombol yang mengunduh file dari internet saat diklik. Aplikasi sudah memiliki satu utas utama yang digunakan untuk seluruh UI. Pada platform Windows, ini berarti mengirim/menerima pesan Windows, menggambar ke kanvas kontrol, mengenali interaksi pengguna, dll. Utas ini pada dasarnya adalah loop raksasa yang berputar dengan sangat cepat. Untuk setiap revolusi utas pemintalan ini, potongan kode tertentu dieksekusi.
Dalam satu lingkungan berulir, unduhan file ini akan memblokir loop ini dari pemintalan, sampai unduhan selesai. Selama waktu ini, utas ini tidak lagi dapat melakukan pembaruan UI, mendeteksi klik pengguna, atau apa pun. Inilah yang menyebabkan Windows menempatkan (tidak merespons) dalam judul bentuk -bentuk seperti itu, karena, yah, seperti yang dikatakan, itu tidak merespons.
Di sinilah utas tambahan masuk. Perlu menanggapi Windows. Alih -alih memblokir utas UI utama dengan unduhan file raksasa ini, Anda dapat memasukkan unduhan file itu ke utas lain. Hanya sesederhana itu, bukan?
Anda mungkin bertanya pada diri sendiri, "Bagaimana cara memantau kemajuannya?" atau "Bagaimana cara saya diberitahu ketika selesai?" Ini berarti utas unduhan perlu berinteraksi dengan utas utama. Di sinilah kebingungan masuk. Satu utas tidak bisa begitu saja mengganggu utas lain, karena tidak ada yang tahu pada titik mana satu utas sebenarnya. Ada dua loop terpisah sekarang, dan ketika Anda ingin memperbarui UI, utas UI itu bisa melakukan apa saja. Yang paling penting, misalkan utas UI utama adalah dalam proses menulis string ke properti kontrol yang sama yang juga ingin ditulis oleh utas Anda yang lain. Sekarang Anda memiliki dua utas yang mencoba menulis ke alamat memori yang sama, yang dapat mengakibatkan masalah yang tidak dapat diprediksi.
Dengan menyinkronkan. Kelas TTHREAD Delphi memiliki metode sinkronisasi () yang memungkinkan utas untuk berinteraksi dengan utas UI utama hanya pada saat ketika itu benar -benar akan berperilaku dengan benar, ketika itu benar -benar mengharapkan kejadian seperti itu. Kode yang disinkronkan dari utas lain tidak benar -benar berjalan dalam konteks utas itu - selalu berjalan dalam konteks utas UI utama. Itulah ide sinkronisasi (), adalah untuk menjalankan kode di utas UI.
Jadi pada akhirnya, Anda tidak benar -benar menggunakan VCL dari utas. Sebagai gantinya, utas Anda mengirimkan sinyal ke utas utama, dan hanya ketika utas utama siap menjalankan kode itu. Sementara itu, utas sekunder Anda kemudian diblokir saat menunggu utas utama selesai.
Lalu ada kesalahan dengan berpikir operasi UI besar akan lebih baik di utas. Katakanlah Anda memiliki daftar di mana Anda ingin mengisi jutaan item. Tentu saja itu akan memakan waktu, dan selama waktu ini aplikasi Anda tidak akan merespons. Lagi. Jadi, pindahkan kode itu ke utas, bukan?
Sekali lagi, interaksi UI apa pun harus dilakukan dari utas utama, dan utas utama saja. Utas berguna jika Anda perlu melakukan perhitungan yang panjang, memproses sejumlah besar data, menunggu respons dari sumber daya jarak jauh, atau apa pun yang memakan waktu dan tidak terkait langsung dengan UI.
Itu sulit untuk dikatakan. Tetapi ada praktik umum yang sangat disarankan saat menulis utas: Letakkan kode utas Anda di unitnya sendiri. Unit ini harus diisolasi dari unit UI lainnya. Seharusnya bahkan tidak memiliki unit terkait VCL dalam klausul penggunaannya. Utas seharusnya tidak tahu bagaimana itu digunakan. Itu pada dasarnya harus boneka, dengan satu -satunya tujuan melakukan tugas panjang Anda. Ketika datang ke pembaruan UI dari utas, ini paling baik dilakukan oleh acara yang disinkronkan.
Persis seperti apa kedengarannya. Ini adalah peristiwa yang disinkronkan, seperti yang dijelaskan sebelumnya. Suatu acara hanyalah pointer untuk prosedur yang dapat Anda tetapkan ke utas sebelum dimulai. Di dalam utas, ketika Anda perlu memperbarui UI, Anda kemudian akan menggunakan sinkronisasi () untuk memicu acara ini. Dengan desain ini, utas tidak akan pernah tahu bahwa itu bahkan digunakan oleh UI. Pada saat yang sama, Anda juga secara tidak sengaja mencapai abstraksi. Utas menjadi dapat digunakan kembali. Anda dapat memasukkannya ke beberapa proyek lain yang bahkan mungkin tidak memiliki antarmuka pengguna (katakanlah layanan Windows).
Berikut beberapa tautan langsung ke sumber daya terkait tentang keselamatan utas VCL, jika Anda tidak ingin mencari ...
Aplikasi ini menunjukkan penggunaan utas di Delphi. Karena ada banyak hal yang perlu diketahui, mereka dibagi menjadi beberapa bagian yang berbeda untuk tujuan yang berbeda. Setiap topik memiliki setidaknya 1 unit bentuk (tertanam ke dalam lembar tab), dan setidaknya 1 unit yang berdiri sendiri yang berisi fungsinya selain dari antarmuka pengguna. Ini dilakukan dengan sengaja, untuk menunjukkan bahwa utas harus diisolasi dari UI apa pun.
Bentuk utama itu sendiri sebenarnya tidak memiliki logika di dalamnya. Yang dilakukan hanyalah menanamkan formulir menjadi tab. Di event handler FormCreate() , itu membuat banyak panggilan ke EmbedForm() yang membuat formulir untuk setiap lembar tab.
Sebenarnya menggunakan aplikasi ini sangat sederhana. Anda hanya menavigasi ke salah satu tab, dan masing -masing akan memiliki instruksi sendiri.


Menunjukkan bagaimana file dapat diunduh dari internet di utas. Ada satu fungsi universal yang didefinisikan DownloadFile() yang melakukan unduhan. UI memiliki 3 tombol:
Secara default, URL yang akan diunduh adalah file uji yang disediakan oleh ThinkBroadband.com, tetapi Anda dapat menggunakan URL apa pun yang Anda inginkan. Anda juga dapat memilih lokasi untuk menyimpan file. Ini adalah demo yang sangat sederhana, sehingga nama file/perpanjangan nama file lokal perlu disesuaikan dengan kebutuhan Anda - itu tidak akan secara otomatis berubah untuk URL yang Anda unduh (seperti yang biasanya dilakukan browser).

Menunjukkan cara memperbarui bilah kemajuan dari utas yang melakukan tugas yang panjang.

Demonstrasi menggunakan koneksi database dalam utas dan menyinkronkan data ke utas UI.

Menunjukkan banyak utas yang mengonsumsi siklus CPU besar untuk memuat pengujian prosesor Anda.