MFC - Multithreading

Pustaka Microsoft Foundation Class (MFC) menyediakan dukungan untuk aplikasi multithread. Utas adalah jalur eksekusi dalam suatu proses. Saat Anda memulai Notepad, sistem operasi membuat proses dan mulai menjalankan utas utama proses tersebut. Saat utas ini berakhir, begitu pula prosesnya.

Anda dapat membuat utas tambahan di aplikasi Anda jika Anda mau. Semua utas dalam aplikasi MFC diwakili oleh objek CWinThread. Dalam kebanyakan situasi, Anda bahkan tidak perlu membuat objek ini secara eksplisit; alih-alih panggil fungsi pembantu kerangka kerja AfxBeginThread, yang membuat objek CWinThread untuk Anda.

Mari kita lihat contoh sederhana dengan membuat aplikasi berbasis dialog MFC baru.

Step 1 - Ubah Caption dan ID dari Static control menjadi Click on Start Thread button dan IDC_STATIC_TEXT masing-masing.

Step 2 - Seret dua tombol dan tambahkan penangan peristiwa klik untuk tombol-tombol ini.

Step 3 - Tambahkan variabel kontrol untuk kontrol teks statis.

Step 4 - Sekarang tambahkan tiga variabel global berikut di awal file CMFCMultithreadingDlg.cpp.

int currValue;
int maxValue;
BOOL stopNow;

Step 5 - Tambahkan pesan WM_TIMER di kelas CMFCMultithreadingDlg.

Berikut adalah implementasi OnTimer ()

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
   // TODO: Add your message handler code here and/or call default
   CString sStatusMsg;
   sStatusMsg.Format(L"Running: %d", currValue);
   m_ctrlStatus.SetWindowText(sStatusMsg);

   CDialogEx::OnTimer(nIDEvent);
}

Step 6 - Sekarang tambahkan fungsi sampel untuk digunakan di AfxBeginThread di kelas CMFCMultithreadingDlg.

UINT MyThreadProc(LPVOID Param) {
   while (!stopNow && (currValue < maxValue)) {
      currValue++;
      Sleep(50);     // would do some work here
   }
   
   return TRUE;
}

Step 7 - Berikut adalah implementasi event handler untuk tombol Start Thread, yang akan memulai thread.

void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
   // TODO: Add your control notification handler code here
   currValue = 0;
   maxValue = 5000;
   stopNow = 0;
   m_ctrlStatus.SetWindowText(L"Starting...");
   SetTimer(1234, 333, 0); // 3 times per second

   AfxBeginThread(MyThreadProc, 0); // <<== START THE THREAD
}

Step 8 - Berikut adalah implementasi event handler untuk tombol Stop Thread, yang akan menghentikan thread.

void CMFCMultithreadingDlg::OnBnClickedButtonStop() {
   
   // TODO: Add your control notification handler code here
   stopNow = TRUE;
   KillTimer(1234);
   m_ctrlStatus.SetWindowText(L"Stopped");
}

Step 9 - Ini file sumber lengkapnya.

// MFCMultithreadingDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MFCMultithreading.h"
#include "MFCMultithreadingDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMFCMultithreadingDlg dialog

int currValue;
int maxValue;
BOOL stopNow;

CMFCMultithreadingDlg::CMFCMultithreadingDlg(CWnd* pParent /* = NULL*/)
   : CDialogEx(IDD_MFCMULTITHREADING_DIALOG, pParent) {
   m_hIcon = AfxGetApp() -> LoadIcon(IDR_MAINFRAME);
}
void CMFCMultithreadingDlg::DoDataExchange(CDataExchange* pDX) {
   CDialogEx::DoDataExchange(pDX);
   DDX_Control(pDX, IDC_STATIC_TEXT, m_ctrlStatus);
}

BEGIN_MESSAGE_MAP(CMFCMultithreadingDlg, CDialogEx)
   ON_WM_PAINT()
   ON_WM_QUERYDRAGICON()
   ON_BN_CLICKED(IDC_BUTTON_START,
      &CMFCMultithreadingDlg::OnBnClickedButtonStart)
   ON_WM_TIMER()
   ON_BN_CLICKED(IDC_BUTTON_STOP,
      &CMFCMultithreadingDlg::OnBnClickedButtonStop)
END_MESSAGE_MAP()

// CMFCMultithreadingDlg message handlers

BOOL CMFCMultithreadingDlg::OnInitDialog() {
   CDialogEx::OnInitDialog();

   // Set the icon for this dialog. The framework does this automatically
   // when the application's main window is not a dialog
   SetIcon(m_hIcon, TRUE);        // Set big icon
   SetIcon(m_hIcon, FALSE);       // Set small icon

   // TODO: Add extra initialization here

   return TRUE; // return TRUE unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.

void CMFCMultithreadingDlg::OnPaint() {
   if (IsIconic()) {
      CPaintDC dc(this); // device context for painting
      SendMessage(WM_ICONERASEBKGND,
         reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
			
      // Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;

      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
   }else {
      CDialogEx::OnPaint();
   }
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMFCMultithreadingDlg::OnQueryDragIcon() {
   return static_cast<HCURSOR>(m_hIcon);
}

UINT /*CThreadDlg::*/MyThreadProc(LPVOID Param) //Sample function for using in
AfxBeginThread {
   while (!stopNow && (currValue < maxValue)) {
      currValue++;
      Sleep(50); // would do some work here
   }
   return TRUE;
}
void CMFCMultithreadingDlg::OnBnClickedButtonStart() {
   // TODO: Add your control notification handler code here
   currValue = 0;
   maxValue = 5000;
   stopNow = 0;
   m_ctrlStatus.SetWindowText(L"Starting...");
   SetTimer(1234, 333, 0); // 3 times per second

   AfxBeginThread(MyThreadProc, 0); // <<== START THE THREAD
}

void CMFCMultithreadingDlg::OnTimer(UINT_PTR nIDEvent) {
   // TODO: Add your message handler code here and/or call default
   CString sStatusMsg;
   sStatusMsg.Format(L"Running: %d", currValue);
   m_ctrlStatus.SetWindowText(sStatusMsg);

   CDialogEx::OnTimer(nIDEvent);
}

void CMFCMultithreadingDlg::OnBnClickedButtonStop() {
   // TODO: Add your control notification handler code here
   stopNow = TRUE;
   KillTimer(1234);
   m_ctrlStatus.SetWindowText(L"Stopped");
}

Step 10 - Ketika kode di atas dikompilasi dan dijalankan, Anda akan melihat output berikut.

Step 11 - Sekarang klik tombol Start Thread.

Step 12- Klik tombol Stop Thread. Ini akan menghentikan utas.