课上完了连老师见都没见一面QAQ....记录一下该小项目

效果如下:



1、实现文件搜索功能,并封装为类

1)首先是文件搜索类Rapidfinder的构造函数和析构函数和文件信息初始化函数和文件路径规格化函数;重新初始化文件函数

CRapidFinder::CRapidFinder(HWND MainHwnd, CString MatchName, CString MatchDir)
{
m_hThrds = NULL;
InitializeCriticalSection(&m_gCriticalSection);
ThreadSet();
FinderSet(MainHwnd, MatchName, MatchDir);
}
CRapidFinder::~CRapidFinder()
{
DeleteCriticalSection(&m_gCriticalSection);
if (m_hExitEvent)CloseHandle(m_hExitEvent);
} //初始化搜索文件信息
void CRapidFinder::FinderSet(HWND MainHwnd, CString MatchName, CString MatchDir)
{
FinderReset();
m_MainhWnd = MainHwnd; if (!MatchName.IsEmpty())
{
MatchName.MakeUpper();
MatchDir.MakeUpper();//makerupper()将CString字符转化为一个大写的字符串。
m_strFileName = MatchName;
m_Option |= OP_FILENAME;//按位或后赋值,OP_FILENAME为0x01
}
m_strFileDir = MatchDir; m_hExitEvent = CreateEvent(NULL, TRUE, FALSE, L"RAPIDFINDER");//创建事件,手动设置信号,初始化为未激发
CreatePathList();//规格化文件路径
} //初始化创建线程的信息
void CRapidFinder::ThreadSet(LONG MaxThreadCount, int priority)
{
m_Priority = priority;
m_ActiveCount = m_MaxThreadCount = MaxThreadCount;
if (m_hThrds)delete[]m_hThrds;//释放线程句柄数组
m_hThrds = new HANDLE[MaxThreadCount]; } //重新初始化文件
void CRapidFinder::FinderReset()
{
m_lpText = NULL;
m_NextVal = NULL;
m_Option = 0;
m_strFileName = "";
m_strFileDir = "";
m_DirList.RemoveAll();
ResetEvent(m_hExitEvent);//重置为未激发态
m_ExitCode = ERR;
} //规格化文件路径
void CRapidFinder::CreatePathList()
{
Trim(m_strFileDir); if (m_strFileDir.IsEmpty())
{
SetErrNo(0); return;
} int np = 0, op = 0;
CString str;
//当有多个路径同时选择时(即用;分隔)
while ((np = m_strFileDir.Find(';', op)) != -1)
{
str = Trim(m_strFileDir.Mid(op, np - op));
str.TrimRight('\\');//消除“\\”
if (!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
op = np + 1;
}
str = Trim(m_strFileDir.Mid(op, m_strFileDir.GetLength() - op));
str.TrimRight('\\');
if (!str.IsEmpty())m_DirList.AddTail((LPCTSTR)str);
} 构造函数用来初始化临界区,初始化线程信息(线程优先级、最大线程数、线程句柄数组),初始化搜索文件信息(目录,文件名);
析构函数退出临界区,关闭事件句柄; 2)文件搜索函数的第二部分就是:判断搜索方式的MatchProc函数(是按文件名还是特定字符串);查询指定文件里是否包含特定字符的FindTextFromFile()函数;预先处理特定字符串的CalNextPos()函数 //判断搜索文件时的方式,是按文件名还是包含字符
BOOL __fastcall CRapidFinder::MatchProc(CString& findpath)
{
CString fname(findpath);
int pos = fname.ReverseFind('\\');
fname.MakeUpper();
if ((m_Option & OP_FILENAME) && (fname.Find(m_strFileName, pos + 1) == -1))return false;
if ((m_Option & OP_FILETEXT) && !FindTextFromFile(findpath))return false;
return true;
} //查询文件里是否包含我们指定的字符
BOOL __fastcall CRapidFinder::FindTextFromFile(CString& findpath)
{
CFile file;
if (NULL == file.Open(findpath.GetBuffer(0), CFile::modeRead | CFile::typeBinary))return false;
BYTE* Buffer = new BYTE[512];
int nRead;
if (!(nRead = file.Read(Buffer, 512))) { file.Close(); return false; }//如果读回字节数为0,则关闭Cfile
int i = 0, j = 0; while (j < m_TextSize)
if (j == -1 || Buffer[i] == m_lpText[j])//判断是否包含我们指定的字符
{
if (++i == nRead)//如果读回字节数为1,则只需要一轮循环集合
{
/*PeekAndPump();*/
if (!(nRead = file.Read(Buffer, 512))) { file.Close(); return false; }
i = 0;
}
j++;
}
else j = m_NextVal[j];
file.Close();
return true;
} //决定是否从下一位字符再开始匹配。比如在“aab”中搜索“ab”,当在“aab”中有重复的字符时给每一位字符设置一个是否进行到下一位匹配的标志
int* CRapidFinder::CalNextPos()
{
int j = 0, k = -1;
m_NextVal[0] = -1;
while (j < m_TextSize - 1)
if ((k == -1) || (m_lpText[j] == m_lpText[k]))
{
j++; k++;
if (m_lpText[j] != m_lpText[k])m_NextVal[j] = k;
else m_NextVal[j] = m_NextVal[k];
}
else k = m_NextVal[k];
return m_NextVal;
} 3)第三部分就是多线程的处理,包括主线程函数MainThreadProc()、子线程函数ThreadProc()、启动子线程函数StartFinder()、暂停函数PauseFinder()、停止函数StopFinder()、暂停后继续函数ResumeFinder(); //主线程函数,为每个线程分配搜索任务
DWORD WINAPI CRapidFinder::MainThreadProc(LPVOID lpParam)
{
//新建一个finder对象来存储文件信息
CRapidFinder* finder = (CRapidFinder*)lpParam; resume:
//Reset,重新开始
ResetEvent(finder->m_hExitEvent);//重置m_hExitEvent,使之处于未激发态
finder->m_ExitCode = ERR;
finder->m_ActiveCount = finder->m_MaxThreadCount; PostMessage(finder->m_MainhWnd, WM_THREADCOUNT, (WPARAM)(finder->m_ActiveCount), NULL);
//启动子线程
for (int i = 0; i < finder->m_MaxThreadCount; i++)
finder->m_hThrds[i] = StartThread(ThreadProc, lpParam); WaitForMultipleObjects(finder->m_MaxThreadCount, finder->m_hThrds, TRUE, INFINITE);//等待所有线程返回 for (int i = 0; i < finder->m_MaxThreadCount; i++)
CloseHandle(finder->m_hThrds[i]); //关闭所有线程句柄 //查看线程退出原因
switch (finder->m_ExitCode)
{
case PAUSE:SendMessage(finder->m_MainhWnd, WM_THREADPAUSE, NULL, NULL);
ResetEvent(finder->m_hExitEvent);//重置为未激发态,为暂停后重新开始做准备
//等待继续查找
WaitForSingleObject(finder->m_hExitEvent, INFINITE);
goto resume;
//下面两个类似,一个是直接退出,一个是执行完退出
case EXIT:SendMessage(finder->m_MainhWnd, WM_THREADEXIT, EXIT, NULL);
finder->FinderReset();
break;;
case STOP:SendMessage(finder->m_MainhWnd, WM_THREADEXIT, STOP, NULL);
finder->FinderReset();
break;
default:finder->SetErrNo(1); return 0;
}
return 1;
} //启动子线程的函数
HANDLE CRapidFinder::StartThread(LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParam)
{
DWORD ThreadID;//线程id
CRapidFinder* finder = (CRapidFinder*)lpParam;//文件搜索类对象 HANDLE htmp = CreateThread(NULL, 0, lpStartAddress, lpParam, CREATE_SUSPENDED, &ThreadID);
BOOL re = SetThreadPriority(htmp, finder->m_Priority);
ASSERT(re);
ResumeThread(htmp);
return htmp;
} 上述两个函数相互配合,创建指定数目的子线程(在StartFinder()函数初始化子线程信息,创建子线程);主线程使用WaitForMultipleObjects函数等待所有子线程返回,在全部返回后关闭所有句柄;
并且主线程还监听和处理子线程的状态,根据m_ExitCode判断子线程是处于暂停、停止还是暂停后继续的状态(即文件搜索中的暂停、停止、暂停后继续的功能),然后通过设置m_hExitEvent事件对象的激发状态来控制子线程的工作; 2、文件搜索中的开始、暂停、暂停后继续、停止函数
//开始查找
BOOL CRapidFinder::StartFinder()
{ if (m_DirList.IsEmpty()) { SetErrNo(0); return FALSE; }
PostMessage(m_MainhWnd, WM_THREADCOUNT, (WPARAM)m_ActiveCount, NULL); DWORD ThreadID;
//创建主线程
HANDLE hMainThread = CreateThread(NULL, 0, MainThreadProc, (LPVOID)this, CREATE_SUSPENDED, &ThreadID); //线程是在挂起状态下创建的,并且在调用ResumeThread函数之前不会运行 。
ASSERT(hMainThread);
BOOL re = SetThreadPriority(hMainThread, m_Priority);//调整优先级
ASSERT(re);//作用是如果它的条件返回错误,则终止程序执行
ResumeThread(hMainThread);
CloseHandle(hMainThread); return TRUE;
}
//暂停查找
void CRapidFinder::PauseFinder()
{
if (m_ExitCode == PAUSE)return;
m_ExitCode = PAUSE;
SetEvent(m_hExitEvent);//发出m_hExitEvent信号
Sleep(40);
}
//继续查找
void CRapidFinder::ResumeFinder()
{
SetEvent(m_hExitEvent);
}
//停止查找
void CRapidFinder::StopFinder()
{
if (m_ExitCode == STOP)return; if (m_ExitCode == PAUSE)
{
ResumeFinder();//重新开始
Sleep(40);//延时
}
m_ExitCode = STOP;
SetEvent(m_hExitEvent);
}
在StartFinder()中创建主线程;暂停、暂停后继续、停止都是通过改变m_hExitEvent的激发状态来实现
因为创建m_hExitEvent事件时:CreateEvent(NULL, TRUE, FALSE, L"RAPIDFINDER");是手动重置激发状态,所以在主函数的个状态的处理逻辑里每次都需要先用resetEvent()重置激发态

2、MFC界面

主要用到了mfc的按钮控件、Edit控件和list控件

主要界面布局如上

相关成员的定义:

事件处理程序(函数)的实现

1)MFC类的初始化,对相关成员变量赋初值;以及对话框界面的初始化(设置菜单,图标),另外还使用到了CListCtrl控件来显示搜索到的文件信息

CFinderDemoDlg::CFinderDemoDlg(CWnd* pParent /=NULL/)
: CDialog(CFinderDemoDlg::IDD, pParent)
{ //{{AFX_DATA_INIT(CFinderDemoDlg)
m_ActiveCount = _T("0");
m_folder = _T("");//C:\;D:\;E:\;F:");
m_count = _T("0");
m_findfolder = _T("");
m_text = _T("");
m_filename = _T("");
m_threadcount = 10;
m_priority = 0;
//}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_folder=GetAllDriverList();
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);//图标 } //初始化对话框
BOOL CFinderDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); m_ListCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_TRACKSELECT|LVS_EX_FLATSB|LVS_EX_UNDERLINEHOT|LVS_EX_GRIDLINES);//具体参考https://docs.microsoft.com/zh-cn/windows/win32/Controls/extended-list-view-styles m_ListCtrl.InsertColumn(0,T("文件名"),LVCFMT_IMAGE|LVCFMT_LEFT,80,80);//插入一列
m_ListCtrl.InsertColumn(1,T("路径"),LVCFMT_LEFT,180);
m_ListCtrl.InsertColumn(2,T("大小"),LVCFMT_LEFT,80);
m_ListCtrl.InsertColumn(3,T("类型"),LVCFMT_LEFT,80);
m_ListCtrl.SetHoverTime(500);//设置列表视图控件的当前逗留时间 finder.ThreadSet(30);
m_ListCtrl.SetRedraw();//数据更新时闪烁
UIControl(false); 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);//将IDM_ABOUTBOX添加到菜单中
}
} //设置图标
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control
}

2)数据交换函数和消息响应函数

将控件的值传给类中的将变量的值显示到控件上;以及对相关消息的响应函数(如开始、暂停、显示“正在查找的文件”的函数…)

void CFinderDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFinderDemoDlg)
//将控件的值传递给指定变量假设为类型1,将变量的值传递给控件假设为类型2
DDX_Control(pDX, IDC_LIST, m_ListCtrl);//类型2
DDX_Control(pDX, IDC_STOP, m_stop);//将IDC_STOP窗口的值传递给m_stop
DDX_Control(pDX, IDC_PAUSE, m_pause);//类型1
DDX_Control(pDX, IDC_START, m_start);//类型1
DDX_Text(pDX, IDC_ACTIVE_THREAD, m_ActiveCount);//将m_ActiveCount的值显示到IDC_ACTIVE_THREAD窗口
DDX_Text(pDX, IDC_FOLDER, m_folder);//类型1
DDX_Text(pDX, IDC_COUNT, m_count);//类型2
DDX_Text(pDX, IDC_FINDING_FOLDER, m_findfolder);//将m_findfolder的值显示到IDC_FINDING_FOLDER窗口
DDX_Text(pDX, IDC_INCLUDE_TEXT, m_text);//类型1
DDX_Text(pDX, IDC_FILENAME, m_filename);//类型1
DDX_Text(pDX, IDC_THREAD_NO, m_threadcount);//类型1
//DDX_Text(pDX, IDC_PRIORITY, m_priority);
//}}AFX_DATA_MAP
} BEGIN_MESSAGE_MAP(CFinderDemoDlg, CDialog)//添加消息响应函数,为每个消息处理函数加入一个入口。
ON_WM_SYSCOMMAND()//系统消息
ON_WM_PAINT()//绘图消息
ON_WM_QUERYDRAGICON()//查询icon消息
ON_BN_CLICKED(IDC_STOP, OnStop)//停止
ON_BN_CLICKED(IDC_START, OnStart)//开始
ON_BN_CLICKED(IDC_PAUSE, OnPause)//暂停
ON_BN_CLICKED(IDC_BROWSE, OnBrowse)//选择文件
ON_EN_CHANGE(IDC_THREAD_NO, OnChangeThreadNo)//设置线程数
ON_MESSAGE(WM_THREADEXIT, OnFindExit)//查找时停止
ON_MESSAGE(WM_THREADCOUNT, OnFindThreadCount)
ON_MESSAGE(WM_FINDERITEM , OnFindItem)
ON_MESSAGE(WM_THREADPAUSE, OnFindPause)//查找时暂停
ON_MESSAGE(WM_FINDERFOLDER, OnFindingFolder)//正在查找
ON_EN_CHANGE(IDC_FOLDER, &CFinderDemoDlg::OnEnChangeFolder)
END_MESSAGE_MAP()

3)文件相关函数,OnBrowse()选择在哪个路径进行查找文件;修改查找文件的线程数的OnChangeThreadNo()函数;

点击选择文件按钮,触发OnBrowse事件处理函数,打开选择文件路径的面板;在mfc界面上设置线程数目,通过值交换函数,将控件上的值赋给相关类的成员变量,再通过OnChangeThreadNo()函数修改创建线程是默认设置的线程数目为新的值

//选择查找文件路径

void CFinderDemoDlg::OnBrowse()
{
// TODO: Add your control notification handler code here
BROWSEINFO bi;
char dispname[MAX_PATH], path[MAX_PATH];
ITEMIDLIST* pidl;
//
bi.hwndOwner = m_hWnd;
bi.pidlRoot = 0;
bi.pszDisplayName = dispname;
bi.lpszTitle = "请选择查找目录:";
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;
bi.lpfn = 0;
bi.lParam = 0;
bi.iImage = 0;
if (pidl = SHBrowseForFolder(&bi))
{
SHGetPathFromIDList(pidl, path);
m_folder = CString(path);
if (m_folder.IsEmpty())m_folder = GetAllDriverList();
UpdateData(false);
}
} //当用户未指定查找路径时的默认路径
CString CFinderDemoDlg::GetAllDriverList()
{
CString tmp = _T("D:"), Dir;//D:
for (int i = 1; i <= 25; i++)
{
Dir = CString("D:" + i) + _T(":");
if (GetDriveType(Dir.GetBuffer(0)) == DRIVE_NO_ROOT_DIR)continue;//判断该路径是否是有效的
tmp += ";" + Dir;
}
return tmp;
} //修改默认的线程数为我们MFC界面选择的线程数 void CFinderDemoDlg::OnChangeThreadNo()
{
int count=GetDlgItemInt(IDC_THREAD_NO);
if(count<1||count>99){count=10;SetDlgItemInt(IDC_THREAD_NO,count);}
//finder.ThreadSet(count,finder.GetThreadPrioriy());
finder.ThreadSet(count, m_priority);
}

4)开始、暂停、停止查找文件的函数

//开始
void CFinderDemoDlg::OnStart() {
// TODO: Add your control notification handler code here
// ::SendMessage(GetSafeHwnd(),WM_THREADCOUNT,(WPARAM)100,NULL);
UpdateData(true);//刷新控件的值到变量
m_count = _T("0");
m_ActiveCount = _T("0");
count = 0;
m_imglist.DeleteImageList();
m_imglist.Create(16, 16, ILC_MASK | ILC_COLORDDB, 1, 100);//新建一个图像列表,然后用add添加图标(这里在OnFindItem函数使用到了)
m_ListCtrl.SetImageList(&m_imglist, LVSIL_SMALL);//再将该列表中的图像绑定到m_ListCtrl列表控件上
m_ListCtrl.DeleteAllItems();
UpdateData(false);//将变量刷新到控件进行显示
finder.FinderSet(GetSafeHwnd(), m_filename, m_folder);
finder.FindWithText(m_text, m_text.GetLength());
finder.StartFinder();
UIControl(true);//开始后就调用UIControl进制相关控件接收鼠标或键盘消息
} //暂停
void CFinderDemoDlg::OnPause()
{
// TODO: Add your control notification handler code here
static BOOL ispause = true;
if (ispause)
{
m_pause.SetWindowText("继续");//如果是暂停状态就将按钮修改为“继续”
finder.PauseFinder();
ispause = false;
}
else
{
m_pause.SetWindowText("暂停");
finder.ResumeFinder();
ispause = true;
}
} //停止
void CFinderDemoDlg::OnStop()
{
// TODO: Add your control notification handler code here
finder.StopFinder();
} //弹出框
LRESULT CFinderDemoDlg::OnFindExit(WPARAM wparam, LPARAM lparam) {
m_pause.SetWindowText("暂停");
UIControl(false);
if (wparam == 1)AfxMessageBox("停止查找!");//:AfxMessageBox比MessageBox简单一些,因为它是一个全局函数所以不需要对应的一个窗口类,但是不能控制消息框标题
else AfxMessageBox("查找结束!");
m_ListCtrl.RedrawItems(0, count - 1);//暂停时只显示现在查到的
return 0;
}
LRESULT CFinderDemoDlg::OnFindPause(WPARAM wparam, LPARAM lparam)
{
AfxMessageBox("用户暂停!");
return 0;
}

5)界面更新函数,如更新当前活动线程数,查找到符合的文件数目,开始、暂停、停止的按钮状态,显示正在查找的文件,显示已经找到的符合的文件

LRESULT CFinderDemoDlg::OnFindExit(WPARAM wparam,LPARAM lparam)
{
m_pause.SetWindowText("暂停");
UIControl(false);
if(wparam==1)AfxMessageBox("停止查找!");//:AfxMessageBox比MessageBox简单一些,因为它是一个全局函数所以不需要对应的一个窗口类,但是不能控制消息框标题
else AfxMessageBox("查找结束!");
m_ListCtrl.RedrawItems(0,count-1);//暂停时只显示现在查到的
return 0; } LRESULT CFinderDemoDlg::OnFindPause(WPARAM wparam,LPARAM lparam)
{
AfxMessageBox("用户暂停!");
return 0;
} //查找到的文件的文件信息
LRESULT CFinderDemoDlg::OnFindItem(WPARAM wparam,LPARAM lparam) {
m_count.Format("%d",++count);
UpdateData(false);
CString pathname=*((CString *)wparam);
CFileStatus Status;
CFile::GetStatus(pathname,Status);
CString Unit="Byte";
float flen=(float)Status.m_size;
if(flen>1024)
{
flen/=1024;
if(flen<1024){Unit="KB";}
else{flen/=1024;Unit="MB";}
} CString Size;
Size.Format("%1.2f",flen);
int pos=pathname.ReverseFind('');
SHFILEINFO sfi;
if (::SHGetFileInfo (pathname, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO),SHGFI_USEFILEATTRIBUTES | SHGFI_DISPLAYNAME | SHGFI_TYPENAME |SHGFI_ICON|SHGFI_SMALLICON ))
{
//更新mfc界面的list框显示
m_imglist.Add(sfi.hIcon);
m_ListCtrl.InsertItem(count-1,sfi.szDisplayName,count-1);
m_ListCtrl.SetItemText(count-1,1,pathname.Mid(0,pos));
m_ListCtrl.SetItemText(count-1,2,(Size+Unit));
m_ListCtrl.SetItemText(count-1,3,sfi.szTypeName);
}
m_ListCtrl.Update(count-1);
PeekAndPump();
return 0; } //在MFC界面显示当前活动的线程数
LRESULT CFinderDemoDlg::OnFindThreadCount(WPARAM wparam,LPARAM lparam)
{
m_ActiveCount.Format("%ld",LONG(wparam));
UpdateData(FALSE);
return 0;
} //在mfc界面显示当前正在查询的文件路径
LRESULT CFinderDemoDlg::OnFindingFolder(WPARAM wparam,LPARAM lparam)
{
m_findfolder=*((CString *)wparam);
UpdateData(false);
return 0;
} /控制相关控件的状态
void CFinderDemoDlg::UIControl(BOOL bOp)//start with true;
{
m_start.EnableWindow(!bOp);
m_stop.EnableWindow(bOp);
m_pause.EnableWindow(bOp);
GetDlgItem(IDC_THREAD_NO)->EnableWindow(!bOp);//EnableWindow函数允许/禁止指定的窗口或控件接受鼠标和键盘的输入
GetDlgItem(IDC_SPIN_THREAD_NO)->EnableWindow(!bOp);
}

windows核心编程课程实践---多线程文件搜索器(MFC界面)的更多相关文章

  1. 【Windows核心编程】一个使用内存映射文件进行进程间通信的例子

    进程间通信的方式有很多种,其底层原理使用的都是内存映射文件. 本文实现了Windows核心编程第五版475页上的demo,即使用内存映射文件来在进程间通信. 进程1 按钮[Create  mappin ...

  2. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  3. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  4. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  5. windows核心编程---第八章 使用内核对象进行线程同步

    使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...

  6. 《Windows核心编程》第一讲 对程序错误的处理

    一个Windows函数通常都有一个有意义的返回值类型,它标志着这个函数的运行状态,即函数运行成功与否.windows常用的函数类型如下图: 从系统内部来讲,当一个Windows函数检测到一个错误时,它 ...

  7. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  8. 【Windows】windows核心编程整理(上)

    小续 这是我11年看<windows核心编程>时所作的一些笔记,现整理出来共享给大家 windows核心编程整理(上) windows核心编程整理(下) 线程的基础知识 进程是不活泼的,进 ...

  9. 《windows核心编程系列》十七谈谈dll

    DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...

随机推荐

  1. 2-JVM内存模型

    内存模型 方法区 JDK1.7 之前包含1.7 将方法区称为 Perm Space 永久代 JDK1.8之后包含1.8 将方法区称为 MetaSpace 元空间. 堆(分配内存会大一些) 分配对象.n ...

  2. Spring 学习 之 再探publish-event机制

    之前的文章链接:https://blog.csdn.net/qq_41907991/article/details/88544777 我们要知道的是,Spring的publish-event使用的是监 ...

  3. 【Hadoop离线基础总结】Hue与Hive集成

    目录 1.更改hue的配置hue.ini 2.启动hive的metastore以及hiveserver2服务 3.启动hue进程,查看Hive是否与Hue集成成功 1.更改hue的配置hue.ini ...

  4. 【Hadoop离线基础总结】Hive调优手段

    Hive调优手段 最常用的调优手段 Fetch抓取 MapJoin 分区裁剪 列裁剪 控制map个数以及reduce个数 JVM重用 数据压缩 Fetch的抓取 出现原因 Hive中对某些情况的查询不 ...

  5. JDBC09 CLOB文本大对象

    CLOB(Character Large Object) -用于储存大量的文本数据 BLOB(Binary Large Object) -用于存储大量的二进制数据 -大字段有些特殊,不同数据处理的方式 ...

  6. PAT数列排序

    19考研结束了 .. 还有11天PAT甲 题目链接:http://lx.lanqiao.cn/problem.page?gpid=T52 题目大意:训练排序 解题思路: 方法一: 直接用C++里的so ...

  7. vue 兄弟组件之间的传值

    一. 子传父,父传子. 二. 1.兄弟之间传递数据需要借助于事件车,通过事件车的方式传递数据 2.创建一个Vue的实例,让各个兄弟共用同一个事件机制. 3.传递数据方,通过一个事件触发bus.$emi ...

  8. 一站式Kafka平台解决方案——KafkaCenter

    KafkaCenter是什么 KafkaCenter是一个针对Kafka的一站式,解决方案.用于Kafka集群的维护与管理,生产者和消费者的监控,以及Kafka部分生态组件的使用. 对于Kafka的平 ...

  9. Error: ER_BAD_FIELD_ERROR: Unknown column 'xxx' in 'where clause'

    node中调用mysql模块读写时候,如果直接插入字符串: connection.query('SELECT * from  users WHERE name=' + data.name , call ...

  10. 使用QQ同步助手备份同步手机数据

    QQ同步助手官网:https://pim.qq.com/ QQ同步助手,由腾讯精心打造的云端备份工具.能实现手机之间传输文件,并备份文件.照片.视频.联系人.短信.通讯记录.应用程序到云端的换手机必备 ...