Multithreading: Membuat Utas Pekerja di MFC
Utas pekerja umumnya digunakan untuk menangani tugas latar belakang yang seharusnya tidak harus ditunggu pengguna untuk terus menggunakan aplikasi Anda. Tugas seperti perhitungan ulang dan pencetakan latar belakang adalah contoh utas pekerja yang baik. Topik ini merinci langkah-langkah yang diperlukan untuk membuat utas pekerja. Topik meliputi:
Membuat utas pekerja adalah tugas yang relatif sederhana. Hanya dua langkah yang diperlukan untuk menjalankan utas Anda: menerapkan fungsi pengontrol dan memulai utas. Tidak perlu memperoleh kelas dari CWinThread. Anda dapat memperoleh kelas jika Anda memerlukan versi khusus , CWinThread
tetapi tidak diperlukan untuk utas pekerja yang paling sederhana. Anda dapat menggunakan CWinThread
tanpa modifikasi.
Memulai Utas
Ada dua versi yang kelebihan beban: AfxBeginThread
satu yang hanya dapat membuat utas pekerja, dan satu yang dapat membuat utas antarmuka pengguna dan utas pekerja. Untuk memulai eksekusi utas pekerja Anda menggunakan kelebihan beban pertama, hubungi AfxBeginThread, memberikan informasi berikut:
Alamat fungsi pengontrol.
Parameter yang akan diteruskan ke fungsi pengontrol.
(Opsional) Prioritas yang diinginkan dari utas. Defaultnya adalah prioritas normal. Untuk informasi selengkapnya tentang tingkat prioritas yang tersedia, lihat SetThreadPriority di Windows SDK.
(Opsional) Ukuran tumpukan yang diinginkan untuk utas. Defaultnya adalah tumpukan ukuran yang sama dengan alur pembuatan.
(Opsional) CREATE_SUSPENDED jika Anda ingin utas dibuat dalam status ditangguhkan. Defaultnya adalah 0, atau mulai utas secara normal.
(Opsional) Atribut keamanan yang diinginkan. Defaultnya adalah akses yang sama dengan utas induk. Untuk informasi selengkapnya tentang format informasi keamanan ini, lihat SECURITY_ATTRIBUTES di Windows SDK.
AfxBeginThread
membuat dan menginisialisasi CWinThread
objek untuk Anda, memulainya, dan mengembalikan alamatnya sehingga Anda dapat merujuknya nanti. Pemeriksaan dilakukan di seluruh prosedur untuk memastikan semua objek dibatalkan alokasinya dengan benar jika bagian mana pun dari pembuatan gagal.
Menerapkan Fungsi Pengontrol
Fungsi pengontrol mendefinisikan utas. Ketika fungsi ini dimasukkan, utas dimulai, dan ketika keluar, utas berakhir. Fungsi ini harus memiliki prototipe berikut:
UINT MyControllingFunction( LPVOID pParam );
Parameter adalah nilai tunggal. Nilai yang diterima fungsi dalam parameter ini adalah nilai yang diteruskan ke konstruktor saat objek utas dibuat. Fungsi pengontrol dapat menginterpretasikan nilai ini dengan cara apa pun yang dipilihnya. Ini dapat diperlakukan sebagai nilai skalar atau penunjuk ke struktur yang berisi beberapa parameter, atau dapat diabaikan. Jika parameter mengacu pada struktur, struktur dapat digunakan tidak hanya untuk meneruskan data dari pemanggil ke utas, tetapi juga untuk meneruskan data kembali dari utas ke pemanggil. Jika Anda menggunakan struktur seperti itu untuk meneruskan data kembali ke pemanggil, utas perlu memberi tahu pemanggil saat hasilnya siap. Untuk informasi tentang berkomunikasi dari utas pekerja ke pemanggil, lihat Multithreading: Tips Pemrograman.
Ketika fungsi berakhir, fungsi harus mengembalikan nilai UINT yang menunjukkan alasan penghentian. Biasanya, kode keluar ini adalah 0 untuk menunjukkan keberhasilan dengan nilai lain yang menunjukkan berbagai jenis kesalahan. Ini murni dependen implementasi. Beberapa utas mungkin mempertahankan jumlah penggunaan objek dan mengembalikan jumlah penggunaan objek tersebut saat ini. Untuk melihat bagaimana aplikasi dapat mengambil nilai ini, lihat Multithreading: Mengakhiri Utas.
Ada beberapa batasan tentang apa yang dapat Anda lakukan dalam program multithreaded yang ditulis dengan pustaka MFC. Untuk deskripsi pembatasan ini dan tips lain tentang menggunakan utas, lihat Multithreading: Tips Pemrograman.
Contoh Fungsi Pengontrol
Contoh berikut menunjukkan cara menentukan fungsi pengontrol dan menggunakannya dari bagian lain program.
UINT MyThreadProc( LPVOID pParam )
{
CMyObject* pObject = (CMyObject*)pParam;
if (pObject == NULL ||
!pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
return 1; // if pObject is not valid
// do something with 'pObject'
return 0; // thread completed successfully
}
// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.