C#的线程有thread、timer、dispatch、task等几种类型,而平时在C++工程中也常常会遇到这几种线程模型,我在思考C#是怎么实现的基础上实作了该线程库,希望能简化开发难度。
#ifndef __Easy_Thread_H__
#define __Easy_Thread_H__
#include <stdlib.h>
// 线程对象
typedef uintptr_t easy_thread;
// 任务对象
typedef uintptr_t easy_task;
// 线程入口
typedef int (*easy_thread_startup)(void* param);
// 线程结束
typedef void (*easy_thread_close)(int exitcode, void* param);
// 界面更新
typedef int (*easy_thread_dispatch)(void* param);
// 任务执行
typedef int (*easy_task_startup)(void* param);
// 任务结束
typedef void (*easy_task_close)(int exitcode, void* param);
// easy_thread的消息码
extern const int easy_msg_id;
// 初始化类库
int easy_thread_init();
// 清理类库
int easy_thread_cleanup();
// 新建线程
easy_thread easy_thread_new(easy_thread_startup startup, void* param, easy_thread_close close);
// 等待线程执行完成
void easy_thread_wait(easy_thread thread, int timeout);
// 中断线程执行
void easy_thread_terminate(easy_thread thread);
// 新建界面更新操作
int easy_thread_new_dispatch(void* hWnd, easy_thread_dispatch dispatch, void* param);
// 为Windows的消息处理过程设计的界面线程处理函数
int easy_thread_wnd_proc(void* hWnd, int msg);
// 新建任务
easy_task easy_task_new(easy_task_startup task, void* param, easy_task_close close);
// 取消任务
void easy_task_cancel(easy_task task);
#endif /*__Easy_Thread_H__*/
#include <list>
using namespace std;
#include "easy_thread.h"
#include "simclist.h"
#include <process.h>
#include <Windows.h>
// easy_thread的消息码
const int easy_msg_id = ::RegisterWindowMessageA("easy_msg_id");
// 界面命令列表
static list_t g_easy_thread_dispatch_list;
// 任务命令列表
static list_t g_easy_thread_task_list;
// 任务处理线程
static easy_thread g_easy_thread_task_thread;
// 任务处理事件
static HANDLE g_easy_thread_task_event;
// 任务处理线程退出
static bool g_easy_thread_task_exit;
// 前置声明
static int easy_thread_task_proc(void* param);
// 初始化类库
int easy_thread_init()
{
list_init(&g_easy_thread_dispatch_list);
list_init(&g_easy_thread_task_list);
g_easy_thread_task_exit = false;
g_easy_thread_task_event = CreateEvent(NULL, true, false, NULL);
ResetEvent(g_easy_thread_task_event);
g_easy_thread_task_thread = easy_thread_new(easy_thread_task_proc, NULL, NULL);
return 0;
}
// 清理类库
int easy_thread_cleanup()
{
if (list_iterator_start(&g_easy_thread_dispatch_list) > 0)
{
while (list_iterator_hasnext(&g_easy_thread_dispatch_list) > 0)
{
delete list_iterator_next(&g_easy_thread_dispatch_list);
}
list_iterator_stop(&g_easy_thread_dispatch_list);
}
list_destroy(&g_easy_thread_dispatch_list);
//
g_easy_thread_task_exit = true;
WaitForSingleObject((HANDLE)g_easy_thread_task_thread, INFINITE);
if (list_iterator_start(&g_easy_thread_task_list) > 0)
{
while (list_iterator_hasnext(&g_easy_thread_task_list) > 0)
{
delete list_iterator_next(&g_easy_thread_task_list);
}
list_iterator_stop(&g_easy_thread_task_list);
}
list_destroy(&g_easy_thread_task_list);
return 0;
}
/*
* easy_thread_dispatch_node
*/
class easy_thread_dispatch_node
{
public:
easy_thread_dispatch_node(void* hwnd, easy_thread_dispatch dispatch, void* param)
{
this->hwnd = hwnd;
this->param = param;
this->dispatch = dispatch;
}
public:
void* hwnd;
void* param;
easy_thread_dispatch dispatch;
};
// 为Windows的消息处理过程设计的界面线程处理函数
int easy_thread_wnd_proc(void* hWnd, int msg)
{
if (easy_msg_id != msg)
{
return 0;
}
if (list_iterator_start(&g_easy_thread_dispatch_list) > 0)
{
int iIter = 0;
list<int> delete_list;
easy_thread_dispatch_node* node = NULL;
while (list_iterator_hasnext(&g_easy_thread_dispatch_list) > 0)
{
node = (easy_thread_dispatch_node*)list_iterator_next(&g_easy_thread_dispatch_list);
// 在当前窗口的消息循环内
if (hWnd == node->hwnd)
{
// 执行界面更新命令
if (node->dispatch != NULL)
{
node->dispatch(node->param);
}
// 删除节点
delete node;
// 标记当前节点,需要删除
delete_list.push_back(iIter);
}
iIter++;
}
list_iterator_stop(&g_easy_thread_dispatch_list);
for (auto iter = delete_list.rbegin(); iter != delete_list.rend(); ++iter)
{
list_delete_at(&g_easy_thread_dispatch_list, *iter);
}
}
return 0;
}
/*
* easy_start_address_param
*/
struct easy_start_address_param
{
easy_thread_startup startup;
void* param;
easy_thread_close close;
bool cancel;
easy_start_address_param(easy_thread_startup startup, void* param, easy_thread_close close)
{
this->startup = startup;
this->param = param;
this->close = close;
cancel = false;
}
};
// 线程启动的入口函数
static void __cdecl easy_thread_start_address(void* param)
{
struct easy_start_address_param* addr_param = (struct easy_start_address_param *)param;
if (addr_param != NULL && addr_param->startup != NULL)
{
// 执行线程命令
int exit_code = addr_param->startup(addr_param->param);
if (addr_param->close != NULL)
{
// 通知线程即将退出
addr_param->close(exit_code, addr_param->param);
}
// 删除函数参数
delete addr_param;
}
}
// 新建线程处理函数
easy_thread easy_thread_new(easy_thread_startup startup, void* param, easy_thread_close close)
{
uintptr_t thread = _beginthread(easy_thread_start_address, 0, new easy_start_address_param(startup, param, close));
return thread;
}
// 等待线程执行完成
void easy_thread_wait(easy_thread thread, int timeout)
{
WaitForSingleObject((HANDLE)thread, (timeout == -1) ? INFINITE : timeout);
}
// 中断线程执行
void easy_thread_terminate(easy_thread thread)
{
}
// 新建界面更新操作
int easy_thread_new_dispatch(void* hWnd, easy_thread_dispatch dispatch, void* param)
{
// 将界面更新命令添加到命令队列中
list_append(&g_easy_thread_dispatch_list, new easy_thread_dispatch_node(hWnd, dispatch, param));
// 向需要更新界面的窗口发送界面更新消息
SendMessage((HWND)hWnd, easy_msg_id, 0, 0);
return 0;
}
// 任务处理入口函数
static int easy_thread_task_proc(void* param)
{
while (!g_easy_thread_task_exit)
{
if (list_size(&g_easy_thread_task_list) == 0)
{
ResetEvent(g_easy_thread_task_event);
WaitForSingleObject(g_easy_thread_task_event, 300);
}
else
{
easy_start_address_param* node = (easy_start_address_param*)list_get_at(&g_easy_thread_task_list, 0);
if (!node->cancel && node->startup != NULL)
{
int exitcode = node->startup(node->param);
if (node->close != NULL)
{
node->close(exitcode, node->param);
}
}
// 删除节点
delete node;
list_delete_at(&g_easy_thread_task_list, 0);
}
}
return 0;
}
// 新建任务
easy_task easy_task_new(easy_task_startup task, void* param, easy_task_close close)
{
easy_start_address_param* task_addr = new easy_start_address_param(task, param, close);
// 将任务命令添加到命令队列中
list_append(&g_easy_thread_task_list, task_addr);
SetEvent(g_easy_thread_task_event);
return (easy_task)task_addr;
}
// 取消任务
void easy_task_cancel(easy_task task)
{
easy_start_address_param* task_addr = (easy_start_address_param *)task;
task_addr->cancel = true;
}