在上一节的代码中加入了向文本文件中写入日志的代码:

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输出日志的更多相关文章

  1. c++ 日志输出库 spdlog 简介(1)

    参考文章: log库spdlog简介及使用 - 网络资源是无限的 - CSDN博客 http://blog.csdn.net/fengbingchun/article/details/78347105 ...

  2. c++日志输出库 spdlog 简介(3)多线程控制台输出日志

    spdlog源码分析:https://www.cnblogs.com/eskylin/p/6483199.html spdlog的异步模式使得spdLog可以支持多线程,于是写了一个多线程的小例子: ...

  3. c++ 日志输出库 spdlog 简介(2)

    继续上一篇,example.cpp解析. 1.set_pattern 自定义日志格式 官方参考:https://github.com/gabime/spdlog/wiki/3.-Custom-form ...

  4. 细说Java主流日志工具库

    概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...

  5. 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)

    前言: 本章介绍自己写的基于java.util.logging的轻量级日志记录库(baseLog). 该版本的日志记录库犹如其名,baseLog,是个实现日志记录基本功能的小库,适合小型项目使用,方便 ...

  6. zlog 纯C日志函数库的简单使用方法

    zlog简述: log是一个高性能.线程安全.灵活.概念清晰的纯C日志函数库. 事实上,在C的世界里面没有特别好的日志函数库(就像JAVA里面的的log4j,或者C++的log4cxx).C程序员都喜 ...

  7. Java主流日志工具库

    在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息.在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子.我们先来逐一了解一下主流日志工具. 1.java.util.lo ...

  8. Log4j配置的经典总结,打印日志文件,日志存库

        一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制 日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Sy ...

  9. 如何提升mysql replication的性能&amp;多线程传输二进制日志

    1,最好使用内网或者专线链路传输binlog数据 (千兆网卡.还不够的话,bounding 技术,扩展带宽) 在my.cnf中强制使用内网ip传输数据bind-address=ip2,将二进制保存在独 ...

随机推荐

  1. 第八章 高级搜索树 (b2)B-树:结构

  2. 帧动画 连续播放多张图片动画 以及ui动画 SoundPool

    drawable下有很多图片  可以 <?xml version="1.0" encoding="utf-8"?> <animation-li ...

  3. SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法

    .NET 中 SVN版本冲突中 Files 的值“ < < < < < < < .mine”无效路径中具有非法字符的解决办法: 一. 1.将项目逐个进行编译, ...

  4. metasploit 利用MS08-067渗透攻击xp系统全过程

    工具:metasploit,目标系统 windows xp sp3 English 渗透攻击过程 1.search MS08-067 2. use  exploit/windows/smb/ms08_ ...

  5. 大乐透 Java随机码

    package suijishu; import java.util.Random; // TODO Auto-generated method stub public class Xuanqi { ...

  6. 带你快速进入.net core的世界(转)

    出处:http://www.cnblogs.com/zhaopei/p/netcore.html 阅读目录 vmware虚拟机安装 CentOS7.3安装 Windows的客户端软件 .NET Cor ...

  7. Django入门与实践-第14章:用户注册(完结)

    http://127.0.0.1:8000/signup/ django-admin startapp accounts INSTALLED_APPS = [ 'accounts', ] # mypr ...

  8. schwarz( 施瓦兹)不等式证明

    证明 如果: 函数 y=ax^2+2bx+c 对任意x >=0 时 y>=0; 函数图象在全部x轴上方,故二次方程判别式 b^2-4ac<=0;(即方程无实数解) 即(2b)^2&l ...

  9. UVaLive 2531 The K-League (网络流)

    题意:有 n 个队伍进行比赛,每个队伍比赛数目是一样的,每场恰好一个胜一个负,给定每个队伍当前胜的场数败的数目,以及两个队伍剩下的比赛场数,问你冠军队伍可能是哪些队. 析:对每个队伍 i 进行判断是不 ...

  10. mysql图文安装教程(win7 32位 亲测)

    一.下载mysql:http://www.mysql.com/downloads/ 弹出: 你需要有一个 Oracle Web 帐户,没有的话,注册一个: 勾选许可: 输入搜索条件: 下载MySQL ...