1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 模拟售票大厅实例——多线程时访问共享变量时的安全(CMutex或CCriticalSection的应用)

模拟售票大厅实例——多线程时访问共享变量时的安全(CMutex或CCriticalSection的应用)

时间:2023-12-31 09:27:28

相关推荐

模拟售票大厅实例——多线程时访问共享变量时的安全(CMutex或CCriticalSection的应用)

当程序运行时,可以通过多线程来提高程序运行的效率和拥有更好的体验。但多线程(或多进程)同时也带来很多的问题:最严重的莫过于对同一个对象或变量访问时,由于线程运行异步的原因,会造成程序运行出现无法控制的重大错误。对此,MFC有控制线程或进程同步的封装类:如CMutex或CCriticalSection等等。详细用法不说,直接上代码:

源码:/download/weixin_44027440/11428840

效果图:

SaleTickets.h

// SaleTickets.h: PROJECT_NAME 应用程序的主头文件//#pragma once#ifndef __AFXWIN_H__#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"#endif#include "resource.h"// 主符号// CSaleTicketsApp:// 有关此类的实现,请参阅 SaleTickets.cpp//class CSaleTicketsApp : public CWinApp{public:CSaleTicketsApp();// 重写public:virtual BOOL InitInstance();// 实现DECLARE_MESSAGE_MAP()};extern CSaleTicketsApp theApp;

【SaleTickets.cpp】

// SaleTickets.cpp: 定义应用程序的类行为。//#include "stdafx.h"#include "SaleTickets.h"#include "SaleTicketsDlg.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// CSaleTicketsAppBEGIN_MESSAGE_MAP(CSaleTicketsApp, CWinApp)ON_COMMAND(ID_HELP, &CWinApp::OnHelp)END_MESSAGE_MAP()// CSaleTicketsApp 构造CSaleTicketsApp::CSaleTicketsApp(){// TODO: 在此处添加构造代码,// 将所有重要的初始化放置在 InitInstance 中}// 唯一的 CSaleTicketsApp 对象CSaleTicketsApp theApp;// CSaleTicketsApp 初始化BOOL CSaleTicketsApp::InitInstance(){CWinApp::InitInstance();// 创建 shell 管理器,以防对话框包含// 任何 shell 树视图控件或 shell 列表视图控件。CShellManager *pShellManager = new CShellManager;// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));// 标准初始化// 如果未使用这些功能并希望减小// 最终可执行文件的大小,则应移除下列// 不需要的特定初始化例程// 更改用于存储设置的注册表项// TODO: 应适当修改该字符串,// 例如修改为公司或组织名SetRegistryKey(_T("应用程序向导生成的本地应用程序"));CSaleTicketsDlg dlg;m_pMainWnd = &dlg;INT_PTR nResponse = dlg.DoModal();if (nResponse == IDOK){// TODO: 在此放置处理何时用// “确定”来关闭对话框的代码}else if (nResponse == IDCANCEL){// TODO: 在此放置处理何时用// “取消”来关闭对话框的代码}else if (nResponse == -1){TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");}// 删除上面创建的 shell 管理器。if (pShellManager != nullptr){delete pShellManager;}#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)ControlBarCleanUp();#endif// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,// 而不是启动应用程序的消息泵。return FALSE;}

【SaleTicketsDlg.h】

// SaleTicketsDlg.h: 头文件//#pragma once// CSaleTicketsDlg 对话框class CSaleTicketsDlg : public CDialogEx{// 构造public:CSaleTicketsDlg(CWnd* pParent = nullptr);// 标准构造函数// 对话框数据#ifdef AFX_DESIGN_TIMEenum { IDD = IDD_SALETICKETS_DIALOG };#endifprotected:virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持// 实现protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:static UINT SaleAProc(LPVOID pParam);static UINT SaleBProc(LPVOID pParam);static UINT AutoSaleAProc(LPVOID pParam);static UINT AutoSaleBProc(LPVOID pParam);afx_msg void OnBnClickedButtonSaleA();afx_msg void OnBnClickedButtonSaleB();afx_msg void OnBnClickedButtonAutosale();CWinThread *m_pSaleAThread;CWinThread *m_pSaleBThread;afx_msg void OnBnClickedButtonReset();};

【SaleTicketsDlg.cpp】

// SaleTicketsDlg.cpp: 实现文件//#include "stdafx.h"#include "SaleTickets.h"#include "SaleTicketsDlg.h"#include "afxdialogex.h"#ifdef _DEBUG#define new DEBUG_NEW#endif//全局变量int nTickets;CMutex g_mutex(FALSE, _T("Tickets"));//CCriticalSection g_mutex;// CSaleTicketsDlg 对话框CSaleTicketsDlg::CSaleTicketsDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_SALETICKETS_DIALOG, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);//fdd addnTickets = TICKETSNUM;}void CSaleTicketsDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CSaleTicketsDlg, CDialogEx)ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON_SALE_A, &CSaleTicketsDlg::OnBnClickedButtonSaleA)ON_BN_CLICKED(IDC_BUTTON_SALE_B, &CSaleTicketsDlg::OnBnClickedButtonSaleB)ON_BN_CLICKED(IDC_BUTTON_AUTOSALE, &CSaleTicketsDlg::OnBnClickedButtonAutosale)ON_BN_CLICKED(IDC_BUTTON_RESET, &CSaleTicketsDlg::OnBnClickedButtonReset)END_MESSAGE_MAP()// CSaleTicketsDlg 消息处理程序BOOL CSaleTicketsDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动// 执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码//fdd addSetDlgItemInt(IDC_EDIT_TICKETS, nTickets);return TRUE; // 除非将焦点设置到控件,否则返回 TRUE}// 如果向对话框添加最小化按钮,则需要下面的代码// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,// 这将由框架自动完成。void CSaleTicketsDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中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;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CSaleTicketsDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}UINTCSaleTicketsDlg::SaleAProc(LPVOID pParam) {//解读传送的变量CWnd *pDlg = (CWnd *)pParam;//上锁g_mutex.Lock();if (nTickets > 0) {Sleep(1);CString strName;pDlg->GetDlgItemText(IDC_EDIT_NAME_A, strName);//购票人姓名CListBox *lbSaleA = (CListBox *)pDlg->GetDlgItem(IDC_LIST_NAME_A);//售票窗口ACString s;s.Format(_T("%d--->"), TICKETSNUM+1 - nTickets);s += strName;lbSaleA->AddString(s);pDlg->SetDlgItemInt(IDC_EDIT_TICKETS, --nTickets);}else {AfxMessageBox(_T("你来晚了,票已经卖完了!"));}//解锁g_mutex.Unlock();return 0;}UINTCSaleTicketsDlg::SaleBProc(LPVOID pParam) {//解读传送的变量CWnd *pDlg = (CWnd *)pParam;//上锁g_mutex.Lock();if (nTickets > 0) {Sleep(1);CString strName;pDlg->GetDlgItemText(IDC_EDIT_NAME_B, strName);//购票人姓名CListBox *lbSaleB = (CListBox *)pDlg->GetDlgItem(IDC_LIST_NAME_B);//售票窗口ACString s;s.Format(_T("%d--->"), TICKETSNUM+1 - nTickets);s += strName;lbSaleB->AddString(s);pDlg->SetDlgItemInt(IDC_EDIT_TICKETS, --nTickets);}else {AfxMessageBox(_T("你来晚了,票已经卖完了!"));}//解锁g_mutex.Unlock();return 0;}void CSaleTicketsDlg::OnBnClickedButtonSaleA(){// TODO: 在此添加控件通知处理程序代码m_pSaleAThread = AfxBeginThread(SaleAProc,(LPVOID)this);}void CSaleTicketsDlg::OnBnClickedButtonSaleB(){// TODO: 在此添加控件通知处理程序代码m_pSaleAThread = AfxBeginThread(SaleBProc, (LPVOID)this);}void CSaleTicketsDlg::OnBnClickedButtonAutosale(){// TODO: 在此添加控件通知处理程序代码m_pSaleAThread=AfxBeginThread(AutoSaleAProc, (LPVOID)this);m_pSaleBThread = AfxBeginThread(AutoSaleBProc, (LPVOID)this);}UINT CSaleTicketsDlg::AutoSaleAProc(LPVOID pParam) {//解读传送的变量CWnd *pDlg = (CWnd *)pParam;while (1) {g_mutex.Lock();if (nTickets > 0) {Sleep(1);CString strName;strName.Format(_T("%d--->姓名:无"), TICKETSNUM+1 - nTickets);CListBox *lbSaleA = (CListBox *)pDlg->GetDlgItem(IDC_LIST_NAME_A);//售票窗口AlbSaleA->AddString(strName);pDlg->SetDlgItemInt(IDC_EDIT_TICKETS, --nTickets);g_mutex.Unlock();}else{AfxMessageBox(_T("窗口A提示您:票已经卖完了!"));g_mutex.Unlock();break;}}return 0;}UINT CSaleTicketsDlg::AutoSaleBProc(LPVOID pParam) {//解读传送的变量CWnd *pDlg = (CWnd *)pParam;while (1) {g_mutex.Lock();if (nTickets > 0) {Sleep(1);CString strName;strName.Format(_T("%d--->姓名:无"), TICKETSNUM+1 - nTickets);CListBox *lbSaleB = (CListBox *)pDlg->GetDlgItem(IDC_LIST_NAME_B);//售票窗口AlbSaleB->AddString(strName);pDlg->SetDlgItemInt(IDC_EDIT_TICKETS, --nTickets);g_mutex.Unlock();}else{AfxMessageBox(_T("窗口B提示您:票已经卖完了!"));g_mutex.Unlock();break;}}return 0;}void CSaleTicketsDlg::OnBnClickedButtonReset(){// TODO: 在此添加控件通知处理程序代码nTickets = TICKETSNUM;SetDlgItemInt(IDC_EDIT_TICKETS, nTickets);SetDlgItemText(IDC_EDIT_NAME_A, _T(""));SetDlgItemText(IDC_EDIT_NAME_B, _T(""));((CListBox *)GetDlgItem(IDC_LIST_NAME_A))->ResetContent();((CListBox *)GetDlgItem(IDC_LIST_NAME_B))->ResetContent();}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。