c++ 日志输出库 spdlog 简介(4)- 多线程txt输出日志
在上一节的代码中加入了向文本文件中写入日志的代码:
UINT CMFCApplication1Dlg::Thread1(LPVOID pParam)
{
try{
size_t q_size = ; //queue size must be power of 2
spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::block_retry);
auto console = spd::stdout_color_st("console1");
for (int i = ; i < ; i++){
Sleep();
console->info("Thread 1,Count {}",i);
Sleep();
auto daily = spd::basic_logger_mt("basic1", "logs/basic-log.txt");
daily->info("Thread 1,Count {}", i);
spdlog::drop("basic1"); }
}
catch (const spd::spdlog_ex& ex)
{
std::cout << "Thread 1 Logger failed: " << ex.what() << std::endl;
}
spdlog::drop("console1");
return ;
}
UINT CMFCApplication1Dlg::Thread2(LPVOID pParam)
{
try{
size_t q_size = ; //queue size must be power of 2
spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::block_retry);
auto console = spd::stdout_color_st("console2");
//auto daily2 = spd::basic_logger_mt("basic2", "logs/basic-log.txt");
for (int i = ; i < ; i++){
Sleep();
console->info("Thread 2,Count {}", i);
auto daily = spd::basic_logger_mt("basic2", "logs/basic-log.txt");
daily->info("Thread 2,Count {}", i);
spdlog::drop("basic2");
}
}
catch (const spd::spdlog_ex& ex)
{
std::cout << "Thread 2 Logger failed: " << ex.what() << std::endl;
}
spdlog::drop("console2");
return ;
}
实验表明,两个线程同时运行,由于写入一个的是同一个txt文件basic-log.txt,运行时会发生异常,如下图第二行的 Permission denied。

由于线程1打开了basic-log.txt文件,在其关闭文件也就是drop之前如果线程2也去打开这个文件,就会发生冲突。
如何解决呢?
(1)ex.what()返回const char * 类型,也就是字符串指针,可以在catch中判断异常类型,如果是Permission denied这种类型的异常,可以重新申请输出日志。
(2)或者用一个线程锁,防止两个线程同时访问一个文件。
首先定义两个全局变量:
HANDLE hEvent1 = NULL;
HANDLE hEvent2 = NULL;
然后在按钮函数中初始化两个Event:
void CMFCApplication1Dlg::OnBnClickedButton1()
{
hEvent1 = CreateEvent(NULL, TRUE, FALSE, NULL);//手动复位,初始为无信号
hEvent2 = CreateEvent(NULL, TRUE, TRUE, NULL);//手动复位,初始为有信号
AfxBeginThread(Thread1, this);
AfxBeginThread(Thread2, this);
}
在线程函数中设定互锁机制:
UINT CMFCApplication1Dlg::Thread1(LPVOID pParam)
{
try{
//size_t q_size = 4096; //queue size must be power of 2
//spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::block_retry);
auto console = spd::stdout_color_st("console1");
for (int i = ; i < ; i++){
Sleep();
DWORD dReturn = WaitForSingleObject(hEvent2, INFINITE);
if (WAIT_OBJECT_0 == dReturn)
{
console->info(" Event2 signaled ! ");
ResetEvent(hEvent2);
Sleep();
}
console->info("Thread 1,Count {}",i);
auto daily = spd::basic_logger_mt("basic1", "logs/basic-log.txt");
daily->info("Thread 1,Count {}", i);
spdlog::drop("basic1");
SetEvent(hEvent1);
Sleep();
}
}
catch (const spd::spdlog_ex& ex)
{
std::cout << "Thread 1 Logger failed: " << ex.what() << std::endl;
const char * ExceptionTpye = ex.what();
std::cout<<strlen(ExceptionTpye)<<endl;
}
spdlog::drop("console1");
return ;
}
UINT CMFCApplication1Dlg::Thread2(LPVOID pParam)
{
try{
//size_t q_size = 4096; //queue size must be power of 2
//spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::block_retry);
auto console = spd::stdout_color_st("console2");
for (int i = ; i < ; i++){
Sleep();
DWORD dReturn = WaitForSingleObject(hEvent1, INFINITE);
if (WAIT_OBJECT_0 == dReturn)
{
console->info(" Event1 signaled ! ");
ResetEvent(hEvent1);
Sleep();
}
console->info("Thread 2,Count {}", i);
auto daily = spd::basic_logger_mt("basic2", "logs/basic-log.txt");
daily->info("Thread 2,Count {}", i);
spdlog::drop("basic2");
SetEvent(hEvent2);
}
}
catch (const spd::spdlog_ex& ex)
{
std::cout << "Thread 2 Logger failed: " << ex.what() << std::endl;
}
spdlog::drop("console2");
return ;
}
原理就是:先启动Event2,这样Thread1就可以执行,执行完第一个循环后把Event1置为有信号,Event2为无信号。这样处于等待状态的Thread2就可以执行了,Thread2执行第一个循环之后把Event2置位有信号,Event1置为无信号。
最后发现Thread1和Thread2交替执行!!!!这样子没什么意义吧。。。
放在cpp文件的开头定义为全局变量,输出在类的成员函数中执行,编译没问题,但运行时无输出。为何?
c++ 日志输出库 spdlog 简介(4)- 多线程txt输出日志的更多相关文章
- c++ 日志输出库 spdlog 简介(1)
参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 ...
- c++日志输出库 spdlog 简介(3)多线程控制台输出日志
spdlog源码分析:https://www.cnblogs.com/eskylin/p/6483199.html spdlog的异步模式使得spdLog可以支持多线程,于是写了一个多线程的小例子: ...
- c++ 日志输出库 spdlog 简介(2)
继续上一篇,example.cpp解析. 1.set_pattern 自定义日志格式 官方参考:https://github.com/gabime/spdlog/wiki/3.-Custom-form ...
- 细说Java主流日志工具库
概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...
- 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)
前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...
- zlog 纯C日志函数库的简单使用方法
zlog简述: log是一个高性能.线程安全.灵活.概念清晰的纯C日志函数库. 事实上,在C的世界里面没有特别好的日志函数库(就像JAVA里面的的log4j,或者C++的log4cxx).C程序员都喜 ...
- Java主流日志工具库
在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息.在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子.我们先来逐一了解一下主流日志工具. 1.java.util.lo ...
- Log4j配置的经典总结,打印日志文件,日志存库
一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制 日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Sy ...
- 如何提升mysql replication的性能&多线程传输二进制日志
1,最好使用内网或者专线链路传输binlog数据 (千兆网卡.还不够的话,bounding 技术,扩展带宽) 在my.cnf中强制使用内网ip传输数据bind-address=ip2,将二进制保存在独 ...
随机推荐
- 第八章 高级搜索树 (b2)B-树:结构
- 帧动画 连续播放多张图片动画 以及ui动画 SoundPool
drawable下有很多图片 可以 <?xml version="1.0" encoding="utf-8"?> <animation-li ...
- SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法
.NET 中 SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法: 一. 1.将项目逐个进行编译, ...
- metasploit 利用MS08-067渗透攻击xp系统全过程
工具:metasploit,目标系统 windows xp sp3 English 渗透攻击过程 1.search MS08-067 2. use exploit/windows/smb/ms08_ ...
- 大乐透 Java随机码
package suijishu; import java.util.Random; // TODO Auto-generated method stub public class Xuanqi { ...
- 带你快速进入.net core的世界(转)
出处:http://www.cnblogs.com/zhaopei/p/netcore.html 阅读目录 vmware虚拟机安装 CentOS7.3安装 Windows的客户端软件 .NET Cor ...
- Django入门与实践-第14章:用户注册(完结)
http://127.0.0.1:8000/signup/ django-admin startapp accounts INSTALLED_APPS = [ 'accounts', ] # mypr ...
- schwarz( 施瓦兹)不等式证明
证明 如果: 函数 y=ax^2+2bx+c 对任意x >=0 时 y>=0; 函数图象在全部x轴上方,故二次方程判别式 b^2-4ac<=0;(即方程无实数解) 即(2b)^2&l ...
- UVaLive 2531 The K-League (网络流)
题意:有 n 个队伍进行比赛,每个队伍比赛数目是一样的,每场恰好一个胜一个负,给定每个队伍当前胜的场数败的数目,以及两个队伍剩下的比赛场数,问你冠军队伍可能是哪些队. 析:对每个队伍 i 进行判断是不 ...
- mysql图文安装教程(win7 32位 亲测)
一.下载mysql:http://www.mysql.com/downloads/ 弹出: 你需要有一个 Oracle Web 帐户,没有的话,注册一个: 勾选许可: 输入搜索条件: 下载MySQL ...