纤程不同于线程,纤程和线程的区别
1.系统不认识纤程,所以,多纤程之间的切换完全由程序员自己调度
2.线程上下文之间切换需要开销,纤程之间切换由于完全受程序员控制,所以没有开销
3.多线程可以同步通讯,但是纤程之间完全不需要同步(线程运行受CPU调度影响,纤程不受CPU调度影响,不会产生同步问题)
纤程函数
PVOID ConvertThreadToFiber(PVOID pvParam);
该函数把当前线程转化为纤程,此时纤程已运行,注意这是跟另外一个纤程创建函数跟它的区别之一
返回值:纤程的运行环境的内存地址
LPVOID CreateFiber(
SIZE_T dwStackSize, // 初始栈大小
LPFIBER_START_ROUTINE lpStartAddress, // 纤程函数
LPVOID lpParameter // 纤程函数参数
);
该函数创建一个纤程,下面是lpStartAddress的原型
VOID CALLBACK FiberProc(
PVOID lpParameter // 纤程参数
);
CreateFiber创建纤程之后无法立即运行,还需要调用SwitchToFiber,切换到创建的纤程运行
VOID SwitchToFiber(
LPVOID lpFiber // 纤程的运行环境的内存地址,由ConvertThreadToFiber或者CreateFiber返回
);
若是想撤销纤程,则需要调用DeleteFiber
VOID DeleteFiber(
LPVOID lpFiber // 纤程的运行环境的内存地址
);
GetCurrentFiber可以获取当前纤程的运行环境的内存地址
GetFiberData可以获取纤程当前参数
下面附上源代码
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Counter.rc 使用
//
#define IDD_COUNTER 101
#define IDI_COUNTER 102
#define IDC_FIBER 1000
#define IDC_ANSWER 1001
#define IDC_COUNT 1002
#define IDC_INFO 1003
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
main.cpp
#define _WIN32_WINNT _WIN32_WINNT_LONGHORN //这里一定要写
#include <Windows.h>
#include <windowsx.h>
#include <stdio.h>
#include "resource.h"
typedef enum
{
BPS_STARTOVER,BPS_CONTINUE,BPS_DONE
}BKGNDSTATE;
typedef struct
{
PVOID pFiberUI;
HWND hwnd;
BKGNDSTATE state;
}FIBERINFO,*PFIBERINFO;
void WINAPI FiberFunc(PVOID pvParam);
INT_PTR WINAPI DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
FIBERINFO g_FiberInfo;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR szCmdLine, int iCmdShow)
{
g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL);
PVOID pFiberCounter = NULL;
g_FiberInfo.state = BPS_DONE;
g_FiberInfo.hwnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_COUNTER), NULL, DlgProc);
SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("User Interface"));
//维护一个消息循环
bool fQuit = false;
MSG msg;
while (!fQuit)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
//如果能得到消息
//还要检查是不是对话框消息
if (!IsDialogMessage(g_FiberInfo.hwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
fQuit = (msg.message == WM_QUIT);
}
else
{
switch (g_FiberInfo.state)
{
case BPS_DONE:
WaitMessage();
break;
case BPS_STARTOVER:
if (pFiberCounter != NULL)
{
DeleteFiber(pFiberCounter);
pFiberCounter = NULL;
}
pFiberCounter=CreateFiber(0, FiberFunc, &g_FiberInfo);
g_FiberInfo.state = BPS_CONTINUE;
case BPS_CONTINUE:
SwitchToFiber(pFiberCounter);
SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("User Interface"));
if (g_FiberInfo.state == BPS_DONE)
{
DeleteFiber(pFiberCounter);
pFiberCounter = NULL;
}
break;
}
}
}
DestroyWindow(g_FiberInfo.hwnd);
return 0;
}
INT_PTR WINAPI DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hInstance;
HICON hIcon;
switch (message)
{
case WM_INITDIALOG:
hInstance=GetModuleHandleW(NULL);
hIcon=LoadIcon(hInstance, MAKEINTRESOURCE(IDI_COUNTER));
if (!hIcon)
{
MessageBox(NULL, TEXT("加载资源失败"), TEXT("error"), MB_OK);
return 1;
}
PostMessage(hwnd,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
PostMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SetDlgItemInt(hwnd, IDC_COUNT, 0, false);
return 1;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_COUNT:
if (HIWORD(wParam) == EN_CHANGE)
{
g_FiberInfo.state = BPS_STARTOVER;
}
return 1;
}
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 1;
}
return 0;
}
void WINAPI FiberFunc(PVOID pvParam)
{
PFIBERINFO FiberInfo = (PFIBERINFO)pvParam;
BOOL Suc;
WORD value;
char buffer[MAX_PATH];
UINT Count = GetDlgItemInt(FiberInfo->hwnd, IDC_COUNT, &Suc, false);
SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("Recalculation"));
for (int i = 0; i <= Count; i++)
{
value = HIWORD(GetQueueStatus(QS_ALLEVENTS));
sprintf(buffer, "%u", value);
if ( value!= 0)
{
SwitchToFiber(FiberInfo->pFiberUI);
SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("Recalculation"));
}
SetDlgItemTextA(g_FiberInfo.hwnd, IDC_INFO, buffer);
SetDlgItemInt(FiberInfo->hwnd, IDC_ANSWER, i, FALSE);
Sleep(200);
}
FiberInfo->state = BPS_DONE;
SwitchToFiber(FiberInfo->pFiberUI);
}
Counter.rc
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "Windows.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 英语(美国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_COUNTER DIALOGEX 0, 0, 156, 37
STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Counter"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
LTEXT "Count to:",IDC_STATIC,4,6,34,8
EDITTEXT IDC_COUNT,38,4,40,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "Answer:",IDC_STATIC,90,6,25,8
RTEXT "0",IDC_ANSWER,122,6,23,8
LTEXT "Currently running fiber:",IDC_INFO,4,24,75,8
LTEXT "Fiber",IDC_FIBER,80,24,72,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_COUNTER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 149
TOPMARGIN, 7
BOTTOMMARGIN, 30
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""Windows.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_COUNTER ICON "Counter.ico"
#endif // 英语(美国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
运行截图
这个程序创建了两个纤程,一个纤程负责接收界面消息,另外一个负责计数,当GetQueueStatus接收到消息的时候就切换到维护界面的纤程,否则就进行计数