从类中的线程启动线程 [英] Starting a thread from a thread within a class

查看:65
本文介绍了从类中的线程启动线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有静态方法作为线程入口点的类.将"this"指针传递到静态方法中,以便可以随后调用线程的类"成员函数.稍后,该线程将启动另一个仍在同一类中的线程.我试图以相同的方式启动该线程,并且该线程启动正常,但是它无法访问之前设置的任何成员变量.有可能做我想做的事吗?还是每个类仅应有一个线程,在这种情况下不会出现此问题?

由于我收到了如此多的答复和有用的建议,因此我决定通过添加一些代码来使情况更加清晰,从而修改我原来的问题.但是,这样做时我发现了我的(非常愚蠢的)错误.我敢肯定,这对你们所有人都是显而易见的,但是我已经在首都发表了评论!!!我非常感谢你们提出的非常好的观点,因为它们肯定地教会了我一些知识,并且如果有人看到我的方法有任何缺陷,那么我将非常高兴听到和学习.我认为最终我可能应该在另一个类中拥有第二个线程,以便分离功能.但是至少我知道可以做自己想做的事情.

Hi, I have a class that has a static method as a threads entry point. A ''this'' pointer is passed into the static method in order that the class'' member function for the thread can then be called. Later, this thread starts another thread which is still within the same class. I have tried to start this thread in the same way, and the thread starts fine but it doesn''t have access to any member variables that were set before. Is it possible to do what I am trying to do? Or should there only be one thread per class, in which case this problem would not arise?

As I have had such a huge amount of response and helpful suggestions, I decided to modify my original question by adding some code to make the situation clearer. However, in doing so I spotted my (very dumb) mistake. I''m sure it will be obvious to you all but I have commented it in capitals!!! I''m very grateful for the very good points you have all made as they have certainly taught me a few things, and if anyone can see any flaws with my method then I''d be very pleased to hear and learn. I think ultimately I should probably have the second thread in another class in order to separate the functionalities. But at least I know that it is possible to do what was trying to do.

//constructor
CardThread::CardThread(CardStatus* pCardStatus)
{
	m_pCardStatus = pCardStatus;
}
//destructor - this never got called when I had a breakpoint in, so the reason for my problem is not because the object is destroyed before the second thread starts
CardThread::~CardThread(void)
{
	int i = 1;
}
//the thread entry point - this method is declared in the header as 'static'
DWORD WINAPI CardThread::CreateCardThread(void* pThis)
{
	CardThread* pCardThread = (CardThread*)pThis;
    
	pCardThread->StartCardThread();

	return 0;
}

bool CardThread::StartCardThread()
{
	//Create a DataWriter thread
	DWORD dwDataWriterThreadID;
        //HERE IS MY MISTAKE!!! '(void*)0 should be '(void*)this' !!!		
	HANDLE hDataWriterThread = CreateThread(NULL, NULL, CreateDataWriterThread, (void*)0, NULL,dwDataWriterThreadID);
	//at this point, m_pCardCtrl is valid
        return true;
}

//this is the entry point for the second thread - it is declared as static in the header
DWORD WINAPI CardThread::CreateDataWriterThread(void* pThis)//(LPVOID iValue)
{
        //now m_pCardCtrl is not valid
	CardThread* pCardThread = (CardThread*)pThis;
	pCardThread->DataWriterThread();
	return 0;
}
int CardThread::DataWriterThread()
{
	//this is where it all goes wrong - m_pCardCtrl is still not valid even though this is a non-static
        //member function
	m_pCardCtrl->AllocBulkWriteBuffers();
	
	return 0;
}

推荐答案

为什么您有线程访问不在该线程中的类的成员?我不完全确定您要完成什么,但这听起来并不安全.当您启动线程时,他不应该访问自己以外的任何变量,除非它们受锁定机制(互斥体,临界区等)保护.否则,线程需要使用创建时传递的结构传递他需要执行的任何变量.

Why do you have threads accessing members of a class that''s not in that thread? I''m not entirely sure what you''re trying to accomplish, but it doesn''t sound thread safe at all. When you start a thread, he shouldn''t have access to any variables outside of himself UNLESS they are protected by a locking mechanism (mutex, critical section, etc.). Otherwise, a thread needs to get passed whatever variables he needs to execute using a structure that is passed when it is created.

她的程序员写道:

还是每个类仅应有一个线程,在这种情况下不会出现此问题?

Or should there only be one thread per class, in which case this problem would not arise?


不,类和线程之间没有任何关系.一个类可以产生多个线程(如果需要),并且一个线程可以使用多个类来执行其工作.没有保护(锁定机制,同步),多个线程不应访问相同的变量! ...否则,您最终将面临比赛条件!


No, classes and threads have little to do with one another. A class can spawn multiple threads (IF NECESSARY) and a thread can use multiple classes to execute its work. Multiple threads shouldn''t be accessing the same variables without protection (locking mechanisms, synchronization)! ...otherwise you end up with race conditions!


您当然可以做您想做的事情,并且您认为自己的想法很好,但您却将相反的事情混为一谈.

指针"this"仅传递给实例(非静态)方法,而不传递给静态方法.事情正好相反.这是静态方法和实例方法之间的确切本质区别.

现在,C ++的问题是:_beginthread_beginthreadex期望指向静态函数的指针(与.NET不同,您可以在线程构造函数中使用静态方法的任何一个实例).当然应该使用实例方法!但是如何?您可以使用_beginthreadex将此作为附加参数传递.本文对这种解决方法进行了很好的解释:
http://www.computersciencelab.com/MultithreadingTut1.htm [
就是说,通过实现线程方法的线程包装器类使用线程非常好.在这种情况下,您当然可以随时(不只是在启动时)在包装的线程和其他线程之间交换数据,当然要进行适当的同步.我觉得您几乎找到了正确的解决方案,但是由于某种原因将事情弄混了.不用担心.

还请从我过去的答案中查看包装器类的代码外观和用法:
如何将ref参数传递给线程 [ ^ ],
启动后更改线程(生产者)的参数 [ ^ ].

抱歉,C#(您可以真正使用实例方法)中的代码,而不是C ++中的代码,但其余的方面非常相似,至少是这个主意.



我还要求我的同事为回答这个问题做出贡献.我希望这样的C ++线程包装器类已经以现成的基类或模板类的形式存在,它们可以以纯面向对象的方式派生,而抽象或伪抽象线程方法将被覆盖.我希望这种东西存在于我不记得或不知道的某些C ++库中.让我们来看看.

—SA
You certainly can do what you want and you thinking is very good, but you mixed up things with the opposites.

The pointer "this" is only passed the the instance (non-static) method, and not passed to the static method. Things are just the opposite. This is the exact essential difference between static and instance methods.

Now, the problem with C++ is: _beginthread and _beginthreadex expect a pointer to a static function (unlike .NET where you can use either instance of static method in the thread constructor). Of course you should use instance method! But how? You can pass this as an additional parameter using _beginthreadex. This work-around is well explained in this article:
http://www.computersciencelab.com/MultithreadingTut1.htm[^].

Locate the code sample with the comment "arg list holding the "this" pointer". It shows how to pass "this" and use it int the thread function.

That said, it is very good to use a thread through a thread wrapper class implementing the thread method. In this case, you can exchange data between the wrapped thread and other threads at any time (not just at start), with proper synchronization, of course. I feel that you almost came to right solution, but mixed up thing by some reason. Not to worry.

Please also see how the code of the wrapper class could look and be used from my past answers:
How to pass ref parameter to the thread[^],
change paramters of thread (producer) after it started[^].

I apologize that the code in C# (where you can really use an instance method), not in C++, but the rest is very similar, at least the idea.



I''m also asking my colleagues to contribute to answering this question. I would expect that such C++ thread wrapper class already exists in the form of ready-to-use base class or template class, which could be derived in a purely object-oriented manner with abstract or pseudo-abstract thread method to be overridden. I hope such thing exists in some of the C++ libraries which I don''t remember or don''t know. Let''s see.

—SA


在我的文章中,您将找到SAKryukov建议的设计示例:
集成ACE和ATL [
You''ll find an example of the design suggested by SAKryukov in my article:
Integrating ACE and ATL[^] - and the article also illustrates interaction between threads.

Best regards
Espen Harlinn


这篇关于从类中的线程启动线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆