无法将文件复制到 C++ 队列中的线程
threads that not working to copy a file into queue in C++
我正在尝试执行一个函数,将信息从文件读取到队列中,然后再执行另一个函数,将信息从队列读取到文件中。这两个功能都由线程启用。问题是第一个函数没有正确存储信息,我不知道为什么?谁能帮我?
这是代码:
void MessagesSender::saveMessages()
{
std::string line = "";
std::ifstream file(FILE_TO_READ);
if (file.is_open())
{
while (std::getline(file, line))
{
mutReadToFile.lock();
this->message.push(line);
mutReadToFile.unlock();
}
file.close();
}
else
{
std::cout << "Faild" << std::endl;
}
std::ofstream removeFile(FILE_TO_READ, std::ofstream::out | std::ofstream::trunc); //to delete the file
std::cout << "wait a minute..." << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(60));
}
和另一个函数:
void MessagesSender::sendMessages()
{
std::ofstream file;
std::vector<std::string> connectUsers;
connectUsers = this->getConnectUsers();
file.open(FILE_TO_WRITE, std::ios::app);
if (file.is_open())
{
while (!this->message.empty())
{
for (int i = 0; i < connectUsers.size(); i++)
{
file << connectUsers[i] << ": " << this->message.front() << std::endl;
}
mutReadToFile.lock();
this->message.pop();
mutReadToFile.unlock();
}
file.close();
std::cout << "Copy successfully" << std::endl;
}
else //If the file doesn't open
{
std::cout << "faild :(" << std::endl;;
}
}
这是菜单:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
read.join();
write.join();
system("pause");
return 0;
}
您的线程使用 MessagesSender 的副本。
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
这些按值绑定。使用 std::ref
防止复制 mess
:
std::thread read(&MessagesSender::saveMessages, std::ref(mess));
std::thread write(&MessagesSender::sendMessages, std::ref(mess));
或者,使用指针:
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
现场演示
一如既往,让我添加一个现场演示。
它也
- 显示如何使用lock_guard或unique_lock来使用异常安全锁定
- 修复操作(empty() 是数据竞争,因为它在锁外)
- 使用 C++11 范围
- 使文件流的错误处理变得地道
- 修复关于截断的误导性评论(没有文件被删除,否则,只是
std::remove
吗?)
- 对 ifstream/ofstream 使用 RAII 而不是手动关闭 ()
存在“更大”的功能问题:
- 我假设您希望为所有连接的用户重复发送消息,而不是每次都弹出消息。
- 存在竞争条件。如果您的 sendMessages 线程启动得太早,它将因为队列为空而退出。这是在您的代码中设计的。我会把它留作 reader.
的驱魔
我可能忘记了一些
#include <fstream>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
static const std::string FILE_TO_READ = "input.txt";
static const std::string FILE_TO_WRITE = "output.txt";
struct MessagesSender {
std::mutex _queueMutex;
std::vector<std::string> getConnectUsers() {
return { "john", "alice", "bob" };
}
void printMenu() { std::cout << "I don't know what's for dinner\n"; }
void sendMessages();
void saveMessages();
std::queue<std::string> _messages;
};
void MessagesSender::saveMessages()
{
std::string line;
{
std::ifstream file(FILE_TO_READ);
while (std::getline(file, line)) {
std::lock_guard lock(_queueMutex);
_messages.push(line);
}
if (!file.good() && !file.eof()) {
std::cout << "Faild" << std::endl;
}
} // closes file
{
std::ofstream removeFile(FILE_TO_READ, std::ios::trunc); // to empty the file
}
std::cout << "Input closed" << std::endl;
}
// and the other function:
void MessagesSender::sendMessages()
{
std::ofstream file(FILE_TO_WRITE, std::ios::app);
if (!file) {
std::cout << "faild :(" << std::endl;
return;
}
auto const connectUsers = MessagesSender::getConnectUsers();
std::unique_lock<std::mutex> lock(_queueMutex);
while (!_messages.empty())
{
auto current = _messages.front();
_messages.pop();
lock.unlock();
for (const auto& user : connectUsers) {
file << user << ": " << current << std::endl;
}
lock.lock();
}
std::cout << "Copy successfully" << std::endl;
}
// this is the menu:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
read.join();
write.join();
}
我正在尝试执行一个函数,将信息从文件读取到队列中,然后再执行另一个函数,将信息从队列读取到文件中。这两个功能都由线程启用。问题是第一个函数没有正确存储信息,我不知道为什么?谁能帮我? 这是代码:
void MessagesSender::saveMessages()
{
std::string line = "";
std::ifstream file(FILE_TO_READ);
if (file.is_open())
{
while (std::getline(file, line))
{
mutReadToFile.lock();
this->message.push(line);
mutReadToFile.unlock();
}
file.close();
}
else
{
std::cout << "Faild" << std::endl;
}
std::ofstream removeFile(FILE_TO_READ, std::ofstream::out | std::ofstream::trunc); //to delete the file
std::cout << "wait a minute..." << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(60));
}
和另一个函数:
void MessagesSender::sendMessages()
{
std::ofstream file;
std::vector<std::string> connectUsers;
connectUsers = this->getConnectUsers();
file.open(FILE_TO_WRITE, std::ios::app);
if (file.is_open())
{
while (!this->message.empty())
{
for (int i = 0; i < connectUsers.size(); i++)
{
file << connectUsers[i] << ": " << this->message.front() << std::endl;
}
mutReadToFile.lock();
this->message.pop();
mutReadToFile.unlock();
}
file.close();
std::cout << "Copy successfully" << std::endl;
}
else //If the file doesn't open
{
std::cout << "faild :(" << std::endl;;
}
}
这是菜单:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
read.join();
write.join();
system("pause");
return 0;
}
您的线程使用 MessagesSender 的副本。
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
这些按值绑定。使用 std::ref
防止复制 mess
:
std::thread read(&MessagesSender::saveMessages, std::ref(mess));
std::thread write(&MessagesSender::sendMessages, std::ref(mess));
或者,使用指针:
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
现场演示
一如既往,让我添加一个现场演示。
它也
- 显示如何使用lock_guard或unique_lock来使用异常安全锁定
- 修复操作(empty() 是数据竞争,因为它在锁外)
- 使用 C++11 范围
- 使文件流的错误处理变得地道
- 修复关于截断的误导性评论(没有文件被删除,否则,只是
std::remove
吗?) - 对 ifstream/ofstream 使用 RAII 而不是手动关闭 ()
存在“更大”的功能问题:
- 我假设您希望为所有连接的用户重复发送消息,而不是每次都弹出消息。
- 存在竞争条件。如果您的 sendMessages 线程启动得太早,它将因为队列为空而退出。这是在您的代码中设计的。我会把它留作 reader. 的驱魔
我可能忘记了一些
#include <fstream>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
static const std::string FILE_TO_READ = "input.txt";
static const std::string FILE_TO_WRITE = "output.txt";
struct MessagesSender {
std::mutex _queueMutex;
std::vector<std::string> getConnectUsers() {
return { "john", "alice", "bob" };
}
void printMenu() { std::cout << "I don't know what's for dinner\n"; }
void sendMessages();
void saveMessages();
std::queue<std::string> _messages;
};
void MessagesSender::saveMessages()
{
std::string line;
{
std::ifstream file(FILE_TO_READ);
while (std::getline(file, line)) {
std::lock_guard lock(_queueMutex);
_messages.push(line);
}
if (!file.good() && !file.eof()) {
std::cout << "Faild" << std::endl;
}
} // closes file
{
std::ofstream removeFile(FILE_TO_READ, std::ios::trunc); // to empty the file
}
std::cout << "Input closed" << std::endl;
}
// and the other function:
void MessagesSender::sendMessages()
{
std::ofstream file(FILE_TO_WRITE, std::ios::app);
if (!file) {
std::cout << "faild :(" << std::endl;
return;
}
auto const connectUsers = MessagesSender::getConnectUsers();
std::unique_lock<std::mutex> lock(_queueMutex);
while (!_messages.empty())
{
auto current = _messages.front();
_messages.pop();
lock.unlock();
for (const auto& user : connectUsers) {
file << user << ": " << current << std::endl;
}
lock.lock();
}
std::cout << "Copy successfully" << std::endl;
}
// this is the menu:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
read.join();
write.join();
}