我需要你对wxWidgets的帮助。我有2个线程(1个wxTimer和1个wxThread),我需要在这2个线程之间进行通信。我有一个类,包含在这个类中读/写变量的方法。 (与此对象共享内存)
我的问题是:我在一个线程中使用“new”这个类进行实例化,但我不知道在第二个线程中有必要。因为如果也是instanciate,变量的地址是不同的,我需要沟通所以我需要变量中的值:/
我知道需要wxSemaphore来防止错误何时访问。
感谢您的帮助!
编辑:我的代码
所以,我需要与我的代码建立链接。谢谢大家;)
这是我在班上我的wxTimer的声明: EvtFramePrincipal(IHM)
在.h
EvtFramePrincipal( wxWindow* parent );
#include <wx/timer.h>
wxTimer m_timer;
in .cpp -Constructor EvtFramePrincipal
EvtFramePrincipal::EvtFramePrincipal( wxWindow* parent )
:
FramePrincipal( parent ),m_timer(this)
{
Connect(wxID_ANY,wxEVT_TIMER,wxTimerEventHandler(EvtFramePrincipal::OnTimer),NULL,this);
m_timer.Start(250);
}
所以我用这条线每250ms调用一次OnTimer方法。
我的第二个帖子从EvtFramePrincipal(IHM)开始:
in .h EvtFramePrincipal
#include "../Client.h"
Client *ClientIdle;
in .cpp EvtFramePrincipal
ClientIdle= new Client();
ClientIdle->Run();
在.h客户端(线程)
class Client: public wxThread
public:
Client();
virtual void *Entry();
virtual void OnExit();
在.cpp客户端(线程)
Client::Client() : wxThread()
{
}
所以在这里,没有问题,线程可以吗? 现在我需要这个类在我的2个线程之间使用信使。
#ifndef PARTAGE_H
#define PARTAGE_H
#include "wx/string.h"
#include <iostream>
using std::cout;
using std::endl;
class Partage
{
public:
Partage();
virtual ~Partage();
bool Return_Capteur_Aval()
{ return Etat_Capteur_Aval; }
bool Return_Capteur_Amont()
{ return Etat_Capteur_Amont; }
bool Return_Etat_Barriere()
{ return Etat_Barriere; }
bool Return_Ouverture()
{ return Demande_Ouverture; }
bool Return_Fermeture()
{ return Demande_Fermeture; }
bool Return_Appel()
{ return Appel_Gardien; }
void Set_Ouverture(bool Etat)
{ Demande_Ouverture=Etat; }
void Set_Fermeture(bool Etat)
{ Demande_Fermeture=Etat; }
void Set_Capteur_Aval(bool Etat)
{ Etat_Capteur_Aval=Etat; }
void Set_Capteur_Amont(bool Etat)
{ Etat_Capteur_Amont=Etat; }
void Set_Barriere(bool Etat)
{ Etat_Barriere=Etat; }
void Set_Appel(bool Etat)
{ Appel_Gardien=Etat; }
void Set_Code(wxString valeur_code)
{ Code=valeur_code; }
void Set_Badge(wxString numero_badge)
{ Badge=numero_badge; }
void Set_Message(wxString message)
{
Message_Affiche=wxT("");
Message_Affiche=message;
}
wxString Get_Message()
{
return Message_Affiche;
}
wxString Get_Code()
{ return Code; }
wxString Get_Badge()
{ return Badge; }
protected:
private:
bool Etat_Capteur_Aval;
bool Etat_Capteur_Amont;
bool Etat_Barriere;
bool Demande_Ouverture;
bool Demande_Fermeture;
bool Appel_Gardien;
wxString Code;
wxString Badge;
wxString Message_Affiche;
};
#endif // PARTAGE_H
所以在我的EvtFramePrincipal(wxTimer)中,我为这个类创建了一个新的。但在其他线程(wxThread)中,我需要做些什么才能进行通信?
如果难以理解,那么抱歉:/
答案 0 :(得分:0)
然后主线程应首先创建共享变量。之后,您可以创建两个线程并向它们传递指向共享变量的指针。
因此,他们俩都知道如何与共享变量进行交互。您需要在共享变量的方法中实现互斥锁或wxSemaphore。
答案 1 :(得分:-1)
您可以使用singleton来访问中心对象。
或者,在创建线程之前创建中心对象,并将对中心对象的引用传递给线程。
在中心对象中使用互斥锁以防止同时访问。
在每个线程上创建一个中心对象不是一种选择。
让我们从一些假设开始。 OP表示
我有2个线程(1个wxTimer和1个wxThread)
说实话,我对wxWidgets框架知之甚少,但总是有文档。所以我可以看到:
wxTimer::Notify()
方法。文档没有说明线程执行的任何内容(尽管有一个注释一个定时器只能在主线程中使用,我不知道如何理解)。我猜我们应该期望Notify方法将在某些事件循环或定时器循环线程或线程中执行。wxThread::Entry()
方法的线程执行模型。 运行一个wxThread对象实际上会创建一个运行Entry方法的线程。所以你的问题是你需要在wxTimer::Notify()
和wxThread::Entry()
方法中访问同一个对象。
这个对象:
这不是一个变量,而是一个类中的很多商店
e.g。
struct SharedData {
// NOTE: This is very simplistic.
// since the information here will be modified/read by
// multiple threads, it should be protected by one or more
// mutexes
// so probably a class with getter/setters will be better suited
// so that access with mutexes can be enforced within the class.
SharedData():var2(0) { }
std::string var1;
int var2;
};
你在某处有一个实例:
std::shared_ptr<SharedData> myData=std::make_shared<SharedData>();
或者可能以指针形式或可能作为局部变量或对象属性
你并没有真正使用wxTimer
或wxThread
,但是从它们继承的类(至少wxThread::Entry()
是纯虚拟的。对于wxTimer
你可以将所有者更改为将接收该事件的其他wxEvtHandler
,但您仍需要提供实施。
所以你可以拥有
class MyTimer: public wxTimer {
public:
void Notify() {
// Your code goes here
// but it can access data through the local reference
}
void setData(const std::shared_ptr<SharedData> &data) {
mLocalReference=data
}
private:
std::shared_ptr<SharedData> mLocalReferece
};
需要设置:
MyTimer timer;
timer.setData(myData);
timer.StartOnece(10000); // wake me up in 10 secs.
类似于线程
class MyThread: public wxThread {
public:
void Entry() {
// Your code goes here
// but it can access data through the local reference
}
void setData(const std::shared_ptr<SharedData> &data) {
mLocalReference=data
}
private:
std::shared_ptr<SharedData> mLocalReferece
};
需要设置:
MyThread *thread=new MyThread();
thread->setData(myData);
thread->Run(); // threads starts running.
有时你无法修改MyThread或MyTimer ......或者将对myData的引用路由到线程或计时器实例太难了......或者你太懒或太忙而无法打扰(谨防你的{ {3}} !!!)
我们可以将SharedData调整为:
struct SharedData {
std::string var1;
int var2;
static SharedData *instance() {
// NOTE that some mutexes are needed here
// to prevent the case where first initialization
// is executed simultaneously from different threads
// allocating two objects, one of them leaked.
if(!sInstance) {
sInstance=new SharedData();
}
return sInstance
}
private:
SharedData():var2(0) { } // Note we've made the constructor private
static SharedData *sInstance=0;
};
可以从中访问此对象(因为它只允许创建单个对象) 使用
MyTimer::Notify()
或MyThread::Entry()
SharedData::instance()->var1;
(或为什么简单的解决方案可能会在将来咬你)。
我的主要原因是:
不过,我认为不能完全避免。它有它的用途,它可以解决你的问题,它可以节省你的一天。
您仍然可以使用访问数据的不同实例(或不同实现)的方法围绕中央存储库组织数据。
这个中央存储库可以是单例(它实际上是中心的,通用的和唯一的),但不是共享数据,而是用于检索共享数据的内容,例如,由某个ID标识(使用选项1可能更容易在线程之间共享)
类似的东西:
CentralRepository::instance()->getDataById(sharedId)->var1;
似乎你的对象EvtFramePrincipal
将执行定时器回调,它将包含指向Client对象(线程)的ClientIdle指针......我会这样做: