鱼C论坛

 找回密码
 立即注册
查看: 1229|回复: 4

[已解决]c++ 多线程文件存储问题

[复制链接]
发表于 2023-8-27 17:24:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 猪猪虾 于 2023-8-27 17:37 编辑

(下面回复没有解决本质问题,大家别走)

我脑子已经转不动了,实在看不出来啥地方有问题了

有两个类,一个叫EventAction,另一个叫SteppingAction,一次EventAction的调用,会执行多次的SteppingAction的调用,总的会执行很多次的EventAction
我在EventAction类里面,每次EventAction类运行结束,我就对EventAction进行累加,并且加锁的方式判断当前是第几次EventAction,假设我有20次EventAction要执行,每5次的结果依次保存在一个新的txt文件夹里面,
当满足这个条件,我就EventAction里面重命名txt;

另一方面,在SteppingAction里面,我实时获取EventAction里面的txt的文件名字,然后将结果保存到新的txt里面

但是现在问题是,总是只有第一个默认的txt产生,其他txt在执行结束之后,都没有生成。我打印EventAction和SteppingAction里面的中间过程发现,txt名字的更改都是对的且传递也是对的,那么问题在哪呢

txt相关的主要在两个函数里面
EventAction.c 的 void EventAction::EndOfEventAction(const G4Event* aEvent)
以及 SteppingAction.c的void SteppingAction::UserSteppingAction(const G4Step* step)

  1. //
  2. //
  3. /// \file EventAction.hh
  4. namespace B1
  5. {

  6.     class RunAction;

  7.     class EventAction : public G4UserEventAction
  8.     {
  9.     public:
  10.         EventAction(RunAction* runAction);
  11.         ~EventAction() override;

  12.         void BeginOfEventAction(const G4Event* event) override;
  13.         void EndOfEventAction(const G4Event* event) override;

  14.         void AddEdep(G4int edep) { fEdep += edep; }

  15.         void test();

  16.         G4String Get_newFilename(){return filename_in_Event;};
  17.     private:

  18.         RunAction* fRunAction = nullptr;
  19.         G4double   fEdep = 0.;  //相当于全局变量,能量作加和,在AddEdep实现不断累加

  20.         static std::mutex myLock; // 用于保护需要同步的资源
  21.         static G4int TotalCount ;
  22.         static G4int FileCount ;

  23.         G4String filename_in_Event;
  24.     };
  25. }

复制代码
  1. //
  2. /// \file EventAction.cc
  3. /// \brief Implementation of the B1::EventAction class

  4. namespace B1
  5. {

  6.     std::mutex EventAction::myLock;
  7.     G4int EventAction::TotalCount = 0;
  8.     G4int EventAction::FileCount = 0;

  9.     EventAction::EventAction(RunAction* runAction)
  10.             : fRunAction(runAction)
  11.     {

  12.     }


  13.     EventAction::~EventAction()
  14.     {}

  15.     void EventAction::BeginOfEventAction(const G4Event*)
  16.     {
  17.         fEdep = 0.;
  18.     }

  19.     void EventAction::EndOfEventAction(const G4Event* aEvent)
  20.     {
  21.         std::lock_guard<std::mutex> lock(myLock);  // 加锁

  22.         TotalCount ++;
  23.         filename_in_Event = "NULL";
  24.         if(TotalCount %10000000 ==0)
  25.         {
  26.             FileCount ++;
  27.             filename_in_Event = "DataOfRun_" + std::to_string(FileCount) + ".txt";
  28. //            G4cout<< "*!!!!!!!!!!!!!!!!!!******* EndOfEventAction ,TotalCount : "<< TotalCount <<
  29. //                  ",filename_in_Event :"<<filename_in_Event<<G4endl;
  30.         }

  31.      //   test();
  32.     }

  33.     void EventAction::test()
  34.     {
  35.         G4String temp = "NULL";
  36.         temp = Get_newFilename();
  37.         if(temp == "NULL")
  38.         {
  39.             G4cout<< "*!!!!!!!!!!!!!!!!!!******* in EventAction :NULL "<<G4endl;
  40.         }
  41.         else
  42.         {
  43.             G4cout<< "*!!!!!!!!!!!!!!!!!!******* in EventAction : "<< temp<<G4endl;
  44.         }

  45.     }

  46. }
复制代码

  1. //
  2. /// \file SteppingAction.hh
  3. using namespace std;
  4. namespace B1
  5. {

  6.     class EventAction;

  7.     class SteppingAction : public G4UserSteppingAction
  8.     {
  9.     public:
  10.         SteppingAction(EventAction* eventAction);
  11.         ~SteppingAction() override;
  12.         void UserSteppingAction(const G4Step*) override;
  13.     private:
  14.         EventAction* fEventAction = nullptr;
  15.         G4LogicalVolume* fScoringVolume = nullptr;

  16.         G4String filename;
  17.     };

  18. }
复制代码

  1. //
  2. /// \file SteppingAction.cc
  3. /// \brief Implementation of the B1::SteppingAction class
  4. namespace B1
  5. {
  6.     SteppingAction::SteppingAction(EventAction* eventAction)
  7.             : fEventAction(eventAction)
  8.     {
  9.         filename = "DataOfRun_0.txt";
  10.     }

  11.     SteppingAction::~SteppingAction()
  12.     {}

  13.     void SteppingAction::UserSteppingAction(const G4Step* step) {
  14.         G4String volumeName = step->GetPreStepPoint()->GetPhysicalVolume()->GetName();
  15.         G4String ParticleName = step->GetTrack()->GetDynamicParticle()->GetParticleDefinition()->GetParticleName();

  16.         G4String Newfilename = fEventAction->Get_newFilename();
  17. //        G4cout<< "*!!!!!!!!!!!!!!!!!!******* Newfilename: "<< Newfilename <<G4endl;
  18. //        G4cout<<"#############  gaga : volumeName " << volumeName <<G4endl;
  19. //        if (ParticleName == "gamma" && volumeName == "DetectorArray")
  20.         if (volumeName == "DetectorArray")
  21.         {
  22.             G4int copyNo = step->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(0);  
  23.             G4double edep = step->GetTotalEnergyDeposit();
  24.          
  25.             if(Newfilename  != "NULL")
  26.             {
  27.                 ofstream outf;
  28.                 outf.open(Newfilename,ios::app);
  29.                 outf<< copyNo << ' ' << edep << ' ';
  30.                 outf.close();
  31.             }
  32.             else
  33.             {
  34. //                G4cout<< "*!!!!!!!!!!!!!!!!!!******* in stepAction :NULL , filename = " << filename <<G4endl;
  35.                 ofstream outf;
  36.                 outf.open(filename,ios::app);
  37.                 outf<< copyNo << ' ' << edep << ' ';
  38.                 outf.close();
  39.             }
  40.         }
  41.     }


  42. }
复制代码

最佳答案
2023-8-27 17:25:55
问题的原因是在EventAction类中,每次EventAction类运行结束后,你使用锁来判断当前是第几次EventAction,并根据条件对文件进行重命名。然而,在SteppingAction类中,你实时获取EventAction类中的文件名,并将结果保存到新的文件中。但是,你在SteppingAction类中使用的文件名始终是初始化时的默认文件名,而不是EventAction类中实时更新的文件名。

解决这个问题的方法是,在SteppingAction类中,你应该使用EventAction类的成员函数Get_newFilename()来获取实时更新的文件名。你可以在SteppingAction类的构造函数中将EventAction类的指针作为参数传递,并将其存储在SteppingAction类的成员变量fEventAction中。然后,在UserSteppingAction函数中,使用fEventAction->Get_newFilename()来获取实时更新的文件名。

以下是修改后的代码示例:

  1. // SteppingAction.hh
  2. using namespace std;

  3. namespace B1
  4. {
  5.     class EventAction;

  6.     class SteppingAction : public G4UserSteppingAction
  7.     {
  8.     public:
  9.         SteppingAction(EventAction* eventAction);
  10.         ~SteppingAction() override;
  11.         void UserSteppingAction(const G4Step*) override;
  12.     private:
  13.         EventAction* fEventAction = nullptr;
  14.         G4LogicalVolume* fScoringVolume = nullptr;

  15.         G4String filename;
  16.     };
  17. }

  18. // SteppingAction.cc
  19. namespace B1
  20. {
  21.     SteppingAction::SteppingAction(EventAction* eventAction)
  22.         : fEventAction(eventAction)
  23.     {
  24.         filename = "DataOfRun_0.txt";
  25.     }

  26.     SteppingAction::~SteppingAction()
  27.     {}

  28.     void SteppingAction::UserSteppingAction(const G4Step* step)
  29.     {
  30.         G4String volumeName = step->GetPreStepPoint()->GetPhysicalVolume()->GetName();
  31.         G4String ParticleName = step->GetTrack()->GetDynamicParticle()->GetParticleDefinition()->GetParticleName();

  32.         G4String Newfilename = fEventAction->Get_newFilename();
  33.         // 使用实时更新的文件名Newfilename
  34.         if (volumeName == "DetectorArray")
  35.         {
  36.             G4int copyNo = step->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(0);
  37.             G4double edep = step->GetTotalEnergyDeposit();

  38.             if (Newfilename != "NULL")
  39.             {
  40.                 ofstream outf;
  41.                 outf.open(Newfilename, ios::app);
  42.                 outf << copyNo << ' ' << edep << ' ';
  43.                 outf.close();
  44.             }
  45.             else
  46.             {
  47.                 ofstream outf;
  48.                 outf.open(filename, ios::app);
  49.                 outf << copyNo << ' ' << edep << ' ';
  50.                 outf.close();
  51.             }
  52.         }
  53.     }
  54. }
复制代码


通过这种方式,你将能够在SteppingAction类中使用实时更新的文件名,并将结果保存到正确的文件中。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-8-27 17:25:31 | 显示全部楼层
根据你提供的代码,我看到你使用了互斥锁来保护资源的访问,但是在文件操作部分存在一些问题。

首先,在EventAction类中,你使用Get_newFilename()方法获取当前的文件名。然而,在BeginOfEventActionEndOfEventAction函数中都调用了test()方法,这意味着每次事件开始和结束时都会调用Get_newFilename()方法,导致在同一个事件中可能多次获取相同的文件名。

其次,在SteppingAction类中,在写入文件之前,你也通过fEventAction->Get_newFilename()方法获取文件名,并将其赋值给Newfilename。但是,你并没有在调用ofstream对象的open函数之前检查Newfilename是否为"NULL",这可能导致打开的文件名为空或错误。你应该在打开文件之前检查文件名是否为空。

另外,你在SteppingAction类的构造函数中将filename初始化为"DataOfRun_0.txt",但是在代码中并没有修改filename的值。因此,在执行保存数据到文件的操作时,始终使用的是默认的文件名。

最后,你可以尝试给文件操作的代码添加一些debug信息,例如打印文件名和相关的提示信息,以便更好地排查问题所在。

希望以上解释和建议能够帮助你找到问题所在并解决它。
如果问题已经解决,请设置最佳答案
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-27 17:25:55 | 显示全部楼层    本楼为最佳答案   
问题的原因是在EventAction类中,每次EventAction类运行结束后,你使用锁来判断当前是第几次EventAction,并根据条件对文件进行重命名。然而,在SteppingAction类中,你实时获取EventAction类中的文件名,并将结果保存到新的文件中。但是,你在SteppingAction类中使用的文件名始终是初始化时的默认文件名,而不是EventAction类中实时更新的文件名。

解决这个问题的方法是,在SteppingAction类中,你应该使用EventAction类的成员函数Get_newFilename()来获取实时更新的文件名。你可以在SteppingAction类的构造函数中将EventAction类的指针作为参数传递,并将其存储在SteppingAction类的成员变量fEventAction中。然后,在UserSteppingAction函数中,使用fEventAction->Get_newFilename()来获取实时更新的文件名。

以下是修改后的代码示例:

  1. // SteppingAction.hh
  2. using namespace std;

  3. namespace B1
  4. {
  5.     class EventAction;

  6.     class SteppingAction : public G4UserSteppingAction
  7.     {
  8.     public:
  9.         SteppingAction(EventAction* eventAction);
  10.         ~SteppingAction() override;
  11.         void UserSteppingAction(const G4Step*) override;
  12.     private:
  13.         EventAction* fEventAction = nullptr;
  14.         G4LogicalVolume* fScoringVolume = nullptr;

  15.         G4String filename;
  16.     };
  17. }

  18. // SteppingAction.cc
  19. namespace B1
  20. {
  21.     SteppingAction::SteppingAction(EventAction* eventAction)
  22.         : fEventAction(eventAction)
  23.     {
  24.         filename = "DataOfRun_0.txt";
  25.     }

  26.     SteppingAction::~SteppingAction()
  27.     {}

  28.     void SteppingAction::UserSteppingAction(const G4Step* step)
  29.     {
  30.         G4String volumeName = step->GetPreStepPoint()->GetPhysicalVolume()->GetName();
  31.         G4String ParticleName = step->GetTrack()->GetDynamicParticle()->GetParticleDefinition()->GetParticleName();

  32.         G4String Newfilename = fEventAction->Get_newFilename();
  33.         // 使用实时更新的文件名Newfilename
  34.         if (volumeName == "DetectorArray")
  35.         {
  36.             G4int copyNo = step->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(0);
  37.             G4double edep = step->GetTotalEnergyDeposit();

  38.             if (Newfilename != "NULL")
  39.             {
  40.                 ofstream outf;
  41.                 outf.open(Newfilename, ios::app);
  42.                 outf << copyNo << ' ' << edep << ' ';
  43.                 outf.close();
  44.             }
  45.             else
  46.             {
  47.                 ofstream outf;
  48.                 outf.open(filename, ios::app);
  49.                 outf << copyNo << ' ' << edep << ' ';
  50.                 outf.close();
  51.             }
  52.         }
  53.     }
  54. }
复制代码


通过这种方式,你将能够在SteppingAction类中使用实时更新的文件名,并将结果保存到正确的文件中。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-27 17:31:30 | 显示全部楼层
isdkz 发表于 2023-8-27 17:25
问题的原因是在EventAction类中,每次EventAction类运行结束后,你使用锁来判断当前是第几次EventAction, ...

虽然初始化是固定的文件名,但是在void SteppingAction::UserSteppingAction(const G4Step* step)函数里面,
我做了if判断的,先判断传进来的文件名是不是被更新了,如果被更新了,我就优先使用新的文件名,我的逻辑是没有问题的对吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-27 17:47:32 | 显示全部楼层

回帖奖励 +1 鱼币

领鱼币,再回答
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 13:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表