基于UDP的P2P聊天工具 0.4——线程的和平退出
简介:
1)这是一个Windows的P2P聊天工具的线程管理部分;
2)Thread.h和Thread.cpp可以拿出来用,不受其它部分干扰;
3)相比0.3版,它考虑了线程的和平退出,仍然局域网;
相关内容:
1)线程的和平退出
一、线程的和平退出
通常,对于线程的终止,大致上有两类。一种是类似于TerminateThread的方法,另一种是由线程主动退出。前者的有点在于高效和直接,缺点在于可能造成资源的释放失败。所以,这里采用线程主动return退出的方式进行处理。
操作上,我们可以采用线程函数+任务函数的方式进行处理。当线程对象被赋予一个任务时,由线程函数调用该任务;当线程对象收到终止命令时,由线程函数控制和平退出。一种较为简介的方式可以像这样:
while( !b_stop )
{
task();
}
二、std::thread的封装
这里使用unique_ptr来管理thread。它们俩有一个相似之处,就是都不允许拷贝。那么,假设要使用vector来进行管理,建议使用move语义,如vec.push_back(temp)
。
这里的线程函数,主要由控制变量和for循环构成,然后对任务函数进行调用。任务函数则需要先调用SetRun进行设置。
因为代码比较短,这里就直接上代码了。下面是Thread.h和Thread.cpp。
/***************************************
* class Thread
* 负责调用任务函数和启停线程
****************************************/
#pragma once
#include <thread>
#include <memory>
#include <functional>
#include <chrono>
using namespace std;
enum class SType { THREAD_JOIN, THREAD_DETACH };
class Thread
{
public:
~Thread();
// 设置任务函数,并设置循环次数
bool SetRun(function<void(void)> func, int times = 1);
// 启动线程: 若未设置任务函数,或正在运行,则返回失败
bool Start(SType type = SType::THREAD_DETACH);
// 停止线程: 停止对任务的循环执行,而当前任务会正常执行
void Stop();
private:
unique_ptr<thread> m_thread;
function<void(void)> m_task; // 任务函数
int m_times; // 线程中,当前任务的执行次数
bool m_started; // 当前线程运行状态
// 作为线程函数,循环调用任务函数
void m_threadRun();
};
#include "Thread.h"
Thread::~Thread()
{
Stop();
}
// 设置任务函数,并设置循环次数
bool Thread::SetRun(function<void(void)> func, int times)
{
if (!m_started)
{
m_task = func;
m_times = times;
return true;
}
return false;
}
// 启动线程
bool Thread::Start(SType type)
{
// 若未设置任务函数,或正在运行,则返回false;
if (!m_task || m_started)
return false;
m_started = true;
m_thread = make_unique<thread>(
thread(bind(&Thread::m_threadRun, this))
);
if (type == SType::THREAD_DETACH)
m_thread->detach();
else
m_thread->join();
return true;
}
// 停止线程: 停止对任务的循环执行,而当前任务会正常执行
void Thread::Stop()
{
m_started = false;
}
// 作为线程函数,循环调用任务函数
void Thread::m_threadRun()
{
if (!m_started || !m_task)
return;
// 若预设执行次数小于等于0,则持续循环,直到线程被终止
for (int i = 0; (i < m_times || m_times<=0) && m_started; i++)
{
m_task();
this_thread::sleep_for(chrono::milliseconds(100));
}
m_started = false;
}
若有兴趣,完整的代码下面的地址。不过有些东西还在改。
https://github.com/Jiacheng03/Hailer