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

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. poj1611(并查集简单应用)

    题目链接:http://poj.org/problem?id=1611 思路: 显然是一个并查集的题,很简单,只要将一个group中的学生并在一起,最后遍历1到n-1,看有多少学生的祖先与0的祖先相等 ...

  2. Marriage Match IV(最短路+网络流)

    Marriage Match IV http://acm.hdu.edu.cn/showproblem.php?pid=3416 Time Limit: 2000/1000 MS (Java/Othe ...

  3. 文件Move操作

    #coding=utf-8 import os import shutil stra = "G:/should/v3/a" strb = "G:/should/v3/b& ...

  4. struts2框架值栈的概述之问题一:什么是值栈?

    1. 问题一:什么是值栈? * 值栈就相当于Struts2框架的数据的中转站,向值栈存入一些数据.从值栈中获取到数据. * ValueStack 是 struts2 提供一个接口,实现类 OgnlVa ...

  5. js记录

    --获取后缀名,结果 .jpg var extName = "/upload/head_img/20150902102539.jpg";var ta = extName.subst ...

  6. Hadoop 系列(二)安装配置

    Hadoop 系列(二)安装配置 Hadoop 官网:http://hadoop.apache.or 一.Hadoop 安装 1.1 Hadoop 依赖的组件 JDK :从 Oracle 官网下载,设 ...

  7. cnn 反向bp这个地方怎么推导??

  8. 执行程序---system

    头文件:#include<stdlib.h> 函数原型:int system(const char *command) 参数说明:command被执行的命令,字符串格式 返回值:成功则返回 ...

  9. 外网不能访问阿里云服务器的apache服务

    今天弄了下Ubuntu的服务器,配置了一个LAMP环境的服务器,配置有时间我再来说 但是配置了很长的时间,差不都怕是好几个小时 在配置apache的时候,出现了问题,好不容易把apache服务配置好 ...

  10. 实现KbmMw web server 支持https

    在以前的文章里面介绍过kbmmw 做web server. 前几天红鱼儿非要我给他做一个支持https 的web server. 其实kbmmw 支持https 有好几种方法: 1. 使用isapi ...