原创链接:多线程求PI
工程名:RollingCastPI
类型:基于对话框的MFC程序
编译器:VC++ 6.0
功能:主线程进行控制后台线程 开始/暂停/继续/停止 计算输出PI,控制输出速度,位数.
源文件:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__06C1326B_158A_46FE_BD0B_50BD680BDB8E__INCLUDED_)
#define AFX_STDAFX_H__06C1326B_158A_46FE_BD0B_50BD680BDB8E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
//添加 头文件
#include <afxmt.h> //CEvent 事件类型
#include "TypeConvert.h"
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__06C1326B_158A_46FE_BD0B_50BD680BDB8E__INCLUDED_)
RollingCastPIDlg是主对话框类
// RollingCastPIDlg.h : header file
//
#if !defined(AFX_ROLLINGCASTPIDLG_H__D74F0B2D_EA2B_4F4D_9232_0180FDCABBB5__INCLUDED_)
#define AFX_ROLLINGCASTPIDLG_H__D74F0B2D_EA2B_4F4D_9232_0180FDCABBB5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/
// CRollingCastPIDlg dialog
class CRollingCastPIDlg : public CDialog
{
// Construction
public:
CRollingCastPIDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CRollingCastPIDlg)
enum { IDD = IDD_ROLLINGCASTPI_DIALOG };
CSliderCtrl m_SpeedSlider;
CComboBox m_UpLimitCombox;
CListCtrl m_PiList;
CListCtrl m_ThreadInforList;
CButton m_StopButton;
CButton m_PauseButton;
CButton m_StartButton;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CRollingCastPIDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CRollingCastPIDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnStartButton();
afx_msg void OnPauseButton();
afx_msg void OnStopButton();
afx_msg void OnCustomdrawSpeedSlider(NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_ROLLINGCASTPIDLG_H__D74F0B2D_EA2B_4F4D_9232_0180FDCABBB5__INCLUDED_)
// RollingCastPIDlg.cpp : implementation file
//
#include "stdafx.h"
#include "RollingCastPI.h"
#include "RollingCastPIDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/
// 全局 变量
/
#define NCOUNT 240000
//事件句柄
CEvent g_StartEvent, /*开始*/
g_PauseEvent, /*暂停*/
g_ContinueEvent, /*继续*/
g_StopEvent; /*停止*/
//PI已求位数 计数器,
/* 为保证编译优化打开的情况下,
* 计数器不被放在寄存器中而设置为volatile(易失)变量
* 若放在寄存器中,主线程对它的修改,在辅线程中无影响*/
volatile long g_PiCount=0;
//小数点后位数设定
long g_MaxPoint=1000;
//输出延迟时间,单位/ms
int g_TimeDelay=0;
//线程信息输出
CListCtrl* g_ThreadInforList;
volatile int g_ThreadInforCount=0;
//按钮控制
CButton* g_StartButton;
CButton* g_PauseButton;
CButton* g_StopButton;
//输出控件
CListCtrl* g_PiList;
/
// 全局 函数
/
/*
* 输出辅助线程信息
*/
void PrintList(CString str,CListCtrl& list,volatile int& curCount)
{
CSize size;
size.cx=0;
size.cy=30;
list.InsertItem(curCount++,str);
list.Scroll(size);
}
/*
* 计算PI线程函数
*/
UINT ComputePIThread(LPVOID pParam)
{
if(WaitForSingleObject(g_StartEvent,INFINITE)==WAIT_OBJECT_0)//阻塞等待 开始事件
{
g_StopEvent.ResetEvent(); //清除 开始事件 信号
g_PauseButton->EnableWindow(true);
g_StopButton->EnableWindow(true);
g_StartButton->EnableWindow(FALSE);
PrintList("线程开始->>",*g_ThreadInforList,g_ThreadInforCount);
}
//计算输出PI
int temp;
long a=10000,b=0,c=NCOUNT,d=0,e=0,f[NCOUNT+1],g=0;
int row=-1,column=0;
CSize size;
size.cx=0;size.cy=30;
while(g_PiCount<g_MaxPoint)
{
//求PI算法
while(b <c)
f[b++]=a/5;
while(c> 0)
{
d=0; g=c*2; b=c;
while(1)
{
d+=f[b]*a; f[b]=d%--g;
d/=g--; b--;
if(b)
d*=b;
else
break;
}
temp=e+d/a;
e=d%a;
c-=14;
//在这里分解成单个的
CString singleWord;
for(int div=1000;div>=1;div/=10)
{
//到达指定数目,停止
if(g_PiCount>=g_MaxPoint)
goto PIEnd;
singleWord=TypeConvert::NumberToString(int(temp/div));
temp%=div;
//每输出15个换行
if((g_PiCount%15)==0)
{
row++;
g_PiList->InsertItem(row,singleWord);
g_PiCount++;
g_PiList->Scroll(size);
}
else
{
g_PiList->SetItemText(row,g_PiCount%15,singleWord);
g_PiCount++;
}
//控制延时为g_TimeDelay
Sleep(g_TimeDelay);
//事件等待
if(WaitForSingleObject(g_StopEvent,0)==WAIT_OBJECT_0) //非阻塞等待 停止事件
{
ResetEvent(g_StopEvent); //清除停止事件 信号
PrintList("线程结束!!!(您按了停止)",*g_ThreadInforList,g_ThreadInforCount);
goto ForceEnd;
}
if(WaitForSingleObject(g_PauseEvent,0)==WAIT_OBJECT_0) //非阻塞等待 暂停事件
{
ResetEvent(g_PauseEvent); //清除 暂停事件 信号
g_PauseButton->SetWindowText("继续");
g_StopButton->EnableWindow(FALSE);
PrintList("线程挂起...(等待继续事件)",*g_ThreadInforList,g_ThreadInforCount);
WaitForSingleObject(g_ContinueEvent,INFINITE);//阻塞等待 继续事件
ResetEvent(g_ContinueEvent); //清除 继续事件 信号
g_PauseButton->SetWindowText("暂停");
g_StopButton->EnableWindow(true);
PrintList("线程恢复->(继续事件发生)",*g_ThreadInforList,g_ThreadInforCount);
}
//end of 事件等待
}
}
//end of 计算输出PI
}
PIEnd:
PrintList("线程结束。||(计算完成)",*g_ThreadInforList,g_ThreadInforCount);
ForceEnd:
g_PauseButton->EnableWindow(FALSE);
g_StopButton->EnableWindow(FALSE);
g_StartButton->EnableWindow(true);
return 0;
}
/
// end of 全局 声明
/
/
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CRollingCastPIDlg dialog
CRollingCastPIDlg::CRollingCastPIDlg(CWnd* pParent /*=NULL*/)
: CDialog(CRollingCastPIDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CRollingCastPIDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CRollingCastPIDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRollingCastPIDlg)
DDX_Control(pDX, IDC_SPEED_SLIDER, m_SpeedSlider);
DDX_Control(pDX, IDC_UPLIMIT_COMBO, m_UpLimitCombox);
DDX_Control(pDX, IDC_PI_LIST, m_PiList);
DDX_Control(pDX, IDC_THREAD_LIST, m_ThreadInforList);
DDX_Control(pDX, IDC_STOP_BUTTON, m_StopButton);
DDX_Control(pDX, IDC_PAUSE_BUTTON, m_PauseButton);
DDX_Control(pDX, IDC_START_BUTTON, m_StartButton);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CRollingCastPIDlg, CDialog)
//{{AFX_MSG_MAP(CRollingCastPIDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_START_BUTTON, OnStartButton)
ON_BN_CLICKED(IDC_PAUSE_BUTTON, OnPauseButton)
ON_BN_CLICKED(IDC_STOP_BUTTON, OnStopButton)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_SPEED_SLIDER, OnCustomdrawSpeedSlider)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CRollingCastPIDlg message handlers
BOOL CRollingCastPIDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
/*
* 窗口初始化
*/
//线程信息列表框
g_ThreadInforList=&m_ThreadInforList;
g_ThreadInforList->InsertColumn(0,"辅助线程信息",NULL,200);
//按钮控制
g_StartButton=&m_StartButton;
g_PauseButton=&m_PauseButton;
g_StopButton=&m_StopButton;
g_PauseButton->EnableWindow(false);
g_StopButton->EnableWindow(false);
//PI显示控件
g_PiList=&m_PiList;
g_PiList->SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT|LVS_EX_ONECLICKACTIVATE);
for(int i=0;i<15;i++)
g_PiList->InsertColumn(i,TypeConvert::NumberToString(1+i),LVCFMT_LEFT,24);
//速度控制
m_SpeedSlider.SetRange(0,10,FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CRollingCastPIDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 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 CRollingCastPIDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (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
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CRollingCastPIDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
/*/
* 开始
/*/
void CRollingCastPIDlg::OnStartButton()
{
//条件初始化
g_PiCount=0;
CString smax;
m_UpLimitCombox.GetWindowText(smax);
smax.TrimLeft();smax.TrimRight();
g_MaxPoint=atoi(smax);
m_PiList.DeleteAllItems();
//开始计算线程
AfxBeginThread(ComputePIThread,GetSafeHwnd());
//开始事件
SetEvent(g_StartEvent);
}
/*/
* 暂停
/*/
void CRollingCastPIDlg::OnPauseButton()
{
CString text;
m_PauseButton.GetWindowText(text);
if(text=="暂停")
SetEvent(g_PauseEvent); //暂停事件
else
SetEvent(g_ContinueEvent);//继续事件
UpdateData(false);
}
/*/
* 停止
/*/
void CRollingCastPIDlg::OnStopButton()
{
SetEvent(g_StopEvent); //停止事件
}
/*
* 调节Slider时响延时改变
*/
void CRollingCastPIDlg::OnCustomdrawSpeedSlider(NMHDR* pNMHDR, LRESULT* pResult)
{
g_TimeDelay=m_SpeedSlider.GetPos()*100;
*pResult = 0;
}
TypeConvert是我自己写的类,封装了一些静态的用于类型转换的法方法
// TypeConvert.h: interface for the TypeConvert class.
//
//
#if !defined(AFX_TYPECONVERT_H__5E25438A_748A_4457_8B8A_6B19347C7A82__INCLUDED_)
#define AFX_TYPECONVERT_H__5E25438A_748A_4457_8B8A_6B19347C7A82__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/*/
* 类型转换类
*//
class TypeConvert
{
public:
TypeConvert();
virtual ~TypeConvert();
//数值型->字符串
static CString NumberToString(int num); // int
static CString NumberToString(float fNum,int nPoint=0); // float
static CString NumberToString(double dNum,int nPoint=0);// double
//字符串->char数组指针
static char* StringToChars(CString string);
};
#endif // !defined(AFX_TYPECONVERT_H__5E25438A_748A_4457_8B8A_6B19347C7A82__INCLUDED_)
// TypeConvert.cpp: implementation of the TypeConvert class.
//
//
#include "stdafx.h"
#include "RollingCastPI.h"
#include "TypeConvert.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
TypeConvert::TypeConvert()
{
}
TypeConvert::~TypeConvert()
{
}
/*/
* 数值型->字符串
/*/
// int->CString
CString TypeConvert::NumberToString(int num)
{
CString stringNum;
stringNum.Format("%d",num);
return stringNum;
}
// float->CString
CString TypeConvert::NumberToString(float fNum,int nPoint/*=0*/)
{
CString stringNum;
if(nPoint!=0)
{
CString point;
point.Format("%d",nPoint);
point="%."+point+"f";
stringNum.Format(point,fNum,nPoint);
}
else
stringNum.Format("%f",fNum);
return stringNum;
}
// double->CString
CString TypeConvert::NumberToString(double dNum,int nPoint/*=0*/)
{
CString stringNum;
if(nPoint!=0)
{
CString point;
point.Format("%d",nPoint);
point="%."+point+"lf";
stringNum.Format(point,dNum,nPoint);
}
else
stringNum.Format("%lf",dNum);
return stringNum;
}
/*/
* 字符串->char数组指针
/*/
char* TypeConvert::StringToChars(CString string)
{
int n=string.GetLength();
char * chars=new char[n+1];
for(int i=0;i<n;i++)
chars[i]=string.GetAt(i);
chars[i]=0;
return chars;
}
the end