[英]WinAPI saving results from multiple processes to one file
我试图搜索类似的问题,但没有找到。 由于问题难以理解,将尝试尽可能简单地再次解释。 基本上,我有 3 个 C++ 源文件:
1.MainProcess3args.cpp - 正在执行与互斥锁同步的 2 个进程,第二个和第三个文件使用CreateProcess()
函数运行。 Process2 应始终首先运行,并且该部分工作正常。 该文件接收 3 个参数 - 第一个是需要生成多少个数字,第二个是运行进程之间的时间距离,第三个参数定义进程必须执行多少次。 例如MainProcess.exe 2 5 2
,
第一个参数 2 -生成多少个数字,
第二个参数 5 - 下一个数字生成和计算平均值、最小值、最大值之间的时间距离(以秒为单位)
第三个参数 2 - 我们将生成多少次数字并计算平均值、最小值和最大值。
2.Random.cpp生成 N 个随机值作为参数并将它们保存到 RandomValues.txt 文件中。
3.ReadingRandoms.cpp有3 Threads-计算平均,找到存储在RandomValues.txt文件编号的最小值和最大值。
我想将有关文件和系统信息的给定参数的信息保存到新的 txt 文件中,并保存平均值、最小值和最大值的每个结果,文件应如下所示:
Total numbers: 2 | Version:Multithreads | Machine: OEM ID: 9 Processor Type: 8664 | Replies: 2 | Pause: 5
AVG MIN MAX
value1 value2 value3
values from next numbers generating...
我有 3 个源文件,尝试使用循环for(int i=0;i<argument2;i++)
多种组合来同步该元素,但它从来没有像它应该的那样工作。 当每个进程执行一次时,一切正常。 MainProcess3args.cpp
#include <windows.h>
#include <stdio.h>
#include <pthread.h>
#include <tchar.h>
#include <mutex>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
HANDLE hMutex; //used mutex object to implement spinlock
using namespace std;
SYSTEM_INFO siSysInfo;
int main(int argc, TCHAR *argv[])
{
STARTUPINFO si1 = { 0 }, si2 = { 0 };
si1.cb = sizeof si1;
si2.cb = sizeof si2;
PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };
const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
fstream Results;
Results.open("Results.txt", ios::in | ios::out);
if (!Results.is_open())
cerr << "failed to open file\n";
GetSystemInfo(&siSysInfo);
int n = 0;//first argument, defines, how many files needs to be generated
int times=0;//second argument,defines time distance beetween generating numbers
int repeat = 0;//third argument
n=_tstoi(argv[1]);
times=_tstoi(argv[2]);
repeat=_tstoi(argv[3]);
Results<<"Total numbers: "<<n<<" | Version:Multithreads | Machine: OEM ID: "<<siSysInfo.dwOemId<<" Processor Type: "<<siSysInfo.dwProcessorType<<" | Replies: "<<repeat<<" | Pause: "<<times;
times=times/0.001;
hMutex = CreateMutex(NULL,0,NULL);
//for(int i=0;i<repeat;i++){
if (!CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1)) //CREATE_SUSPENDED argument makes process 1 hanging and waiting until process 2 excecute
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(hMutex,INFINITE); // process2 call WaitForSingleObject(hmutex) first to get mutex
if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))//Process 2 is created and excecuted ...
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(pi2.hProcess, INFINITE);
CloseHandle(pi2.hProcess); //process2 closes
CloseHandle(pi2.hThread);
}
ReleaseMutex(hMutex);//mutex released, process1 unlocked
ResumeThread(pi1.hThread); //Process 1 is resumed and executed
WaitForSingleObject(pi1.hProcess, INFINITE);
CloseHandle(hMutex);
CloseHandle(pi1.hProcess);//process 1 closes
CloseHandle(pi1.hThread);
}
LARGE_INTEGER li;
double PCFreq = 0.0;
__int64 CounterStart = 0;
if(!QueryPerformanceFrequency(&li))
cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
QueryPerformanceCounter(&li);
double c= (li.QuadPart - CounterStart)/PCFreq;
cout<<"Performance time: "<<c<< " miliseconds";
Results.close();
cin.sync();
cin.ignore();
system("pause");
return 0;
}
第一个过程 - Random3args.cpp
#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;
SYSTEM_INFO siSysInfo;
int main( int argc, TCHAR *argv[] )
{
fstream File;
File.open("RandomValues.txt", ios::in | ios::out);
if (!File.is_open())
cerr << "failed to open file\n";
srand( time( NULL ) );
int n = 0;//first argument, defines, how many files needs to be generated
int times=0;//second argument,defines time distance beetween generating numbers
int repeat = 0;//third argument
n=_tstoi(argv[1]);
times=_tstoi(argv[2]);
repeat=_tstoi(argv[3]);
times=times/0.001;
int r=0;
cout<<endl;
for(int j=0;j<repeat;j++)
{
for(int i=0;i<n;i++)
{
r=rand() % 100;
File<<r<<" ";
cout<<r<<"values "; //checking if values are read correctly
}
cout<<endl;
Sleep(times);
}
File.close();
return 0;
}
第二个过程 - ReadingRandoms3args.cpp
#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <vector>
//this program calculates average value of numbers in file, finds minimum and maximum in the file using 3 threads
#define THREADCOUNT 3
using namespace std;
HANDLE hSemaphore; // using semaphore object to synchronize threads
vector<int> Values;
double Average,MIN,MAX;
DWORD Averages(LPVOID* arg)
{
WaitForSingleObject(hSemaphore, INFINITE);
Average = 0;
double Sum = 0;
//for(int j=0;j<repeat;j++)
for (unsigned int i = 0; i < Values.size(); i++) {
//cout << Values[i] << " "; checking, if the values from the file are being read correctly
Sum+=Values[i];
}
Average = Sum/Values.size();
cout<<"The average of given values is: "<<Average<<endl;
ReleaseSemaphore(hSemaphore,1,NULL);
return 0;
}
DWORD Minimum(LPVOID* arg)
{
WaitForSingleObject(hSemaphore, INFINITE);
MIN=Values[0];
for(unsigned int j=0;j<Values.size();j++)
{
if(MIN>Values[j])
{
MIN=Values[j];
}
}
cout<<endl;
cout<<"Minimum value is "<<MIN<<endl;
ReleaseSemaphore(hSemaphore,1,NULL);
return 0;
}
DWORD Maximum(LPVOID* arg)
{
WaitForSingleObject(hSemaphore, INFINITE);
MAX=Values[0];
for(unsigned int k=0;k<Values.size();k++)
{
if(MAX<Values[k])
{
MAX=Values[k];
}
}
cout<<endl;
cout<<"Maximum value is "<<MAX<<endl;
ReleaseSemaphore(hSemaphore,1,NULL);
return 0;
}
int main( int argc, TCHAR *argv[] )
{
// open the file
ifstream File("RandomValues.txt", ios::in);
if (!File.is_open())
cerr << "failed to open file\n";
// read the values
int val;
while (File >> val){
Values.push_back(val);
}
fstream Results;
Results.open("Results.txt", ios::in | ios::out);
if (!Results.is_open())
cerr << "failed to open file\n";
int repeat = _tstoi(argv[3]) ;
//cout<<repeat;
Results<<"AVG "<<"MIN "<<"MAX "<<endl;
hSemaphore=CreateSemaphore(NULL,0,3,NULL);
HANDLE hThreads[3];
DWORD threadID1,threadID2,threadID3;
for(int i=0;i<repeat;i++){
// calculate average of values-first thread
hThreads[0]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Averages, &hSemaphore,0, &threadID1);
// finding minimum - second thread
hThreads[1]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Minimum, &hSemaphore, 0, &threadID2);
// finding maximum - third thread
hThreads[2]=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Maximum, &hSemaphore, 0, &threadID3);
}
ReleaseSemaphore(hSemaphore,1,NULL);
WaitForMultipleObjects(THREADCOUNT, hThreads, TRUE, INFINITE);
for( int i=0; i < THREADCOUNT; i++ ){
CloseHandle(hThreads[i]);
}
CloseHandle(hSemaphore);
Results<<Average<<" "<<MIN<<" "<<MAX<<endl;
File.close();
Results.close();
return 0;
}
Process2 should always run first, and that part works ok.
这里有一个错误。 在MainProcess3args.cpp
挂起Process1
, MainProcess3args.cpp
执行Process2
, Process2
无法读取任何数据,所以应该先执行Process1
,再通过Process1读取。
以下代码:
const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
...
CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1);
...
CreateProcess(target2, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si2, &pi2);
...
只需修改为:
const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\ReadingRandoms3args.exe");
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\Random3args.exe");
...
CreateProcess(target1, GetCommandLine(), 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1);
...
CreateProcess(target2, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si2, &pi2);
...
这样可以保证读取数据的Process2
先挂起,生成随机数据的过程先执行。
源代码有一些小问题。 在MainProcess3args.cpp
,当你写完:
Results << "Total numbers: " << n << " | Version:Multithreads | Machine: OEM ID: " << siSysInfo.dwOemId << " Processor Type: " << siSysInfo.dwProcessorType << " | Replies: " << repeat << " | Pause: " << times;
在此之后,您没有写入文件,但是您的Process2
需要打开文件句柄才能写入结果。 此时,您还没有关闭文件句柄(您在主进程结束时关闭了它)。
所以你需要在主进程写入之后和创建Process2
之前关闭文件句柄。 比如下面的代码:
Results << "Total numbers: " << n << " | Version:Multithreads | Machine: OEM ID: " << siSysInfo.dwOemId << " Processor Type: " << siSysInfo.dwProcessorType << " | Replies: " << repeat << " | Pause: " << times;
Results.close();
最后它对我有用:
编辑:
两个CreateProcess
需要传递GetCommandLine()
参数,否则程序在调用 argv[3] 时会崩溃。我已经更改了我的代码。
否则,您可以使用以下代码输出:
ofstream Results;
Results.open("Results.txt", std::ofstream::out | std::ofstream::app);
if (!Results.is_open())
cerr << "failed to open file\n";
int repeat = _tstoi(argv[3]);
//cout<<repeat;
Results << endl;
Results << "AVG " << "MIN " << "MAX " << endl;
这样就可以将输出的内容追加到Result.txt
而不是覆盖原来的内容。
还有一些资源泄漏问题:
for (int i = 0; i < repeat; i++) {
// calculate average of values-first thread
hThreads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Averages, &hSemaphore, 0, &threadID1);
// finding minimum - second thread
hThreads[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Minimum, &hSemaphore, 0, &threadID2);
// finding maximum - third thread
hThreads[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Maximum, &hSemaphore, 0, &threadID3);
}
当repeat大于1时,运行上述代码会导致之前的hThreads
句柄被覆盖,并保存上次创建的线程句柄。 需要保证线程句柄在每次循环后正常关闭。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.