静态成员函数和线程 [英] static member function and threading

查看:81
本文介绍了静态成员函数和线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好论坛成员

我在这里提出有关MS VC ++ 2010中多线程的问题.我编写了用于蒙特卡洛计算的类.在这一类中,债券投资组合在10年的时间范围内进行评估,并受10,000条利率期限结构的影响,每条路径均由曲线上的至少20个点定义.由于计算需要一些时间,因此我很想看看多线程.在应用msdn网站的创建线程(Windows)"一章中编写的大部分内容时,此过程没有我最初预期的顺利.

该类的示意图如下:

Hello Forum Members

I come here with a question regarding multithreading in MS VC++ 2010. I have written a class for Monte Carlo calculations. In this class a bond portfolio is evaluated over a time horizon of 10 years subject to 10,000 paths of interest rate terms structures, each one defined by at least 20 points on the curve. As the calculation takes some time I was tempted to have a look at multithreading. This did not proceed as smoothly as initially I had expected while applying most of what is written in the chapter "Creating Threads (Windows) of the msdn web sites.

The class looks schematically like this:

Class MC_Simulation{
	SCENARIO 	Scenarios[10,000];
		
	PORTFOLIO	Bond_Portfolio;
public:
	MC_Simulaion(void);
	~MC_Simulation(void);
	void read_scenario_data_file(const char* file);
	void read_portfolio_data_file(const char* file);
	void initiate_threads(void);
	static DWORD WINAPI bond_portfolio_thread_function(LPVOID arg);

}  // end class


根本问题是必须将"bond_portfolio_thread_function"声明为静态,并且不能再访问Scenarios []和Bond_Portfolio类的信息.我怎样才能从这里开始?

事实是场景数据在模拟过程中不会改变.线程函数应该使用(固定)方案数据来评估Bond_Portfolio中的债券.对于每种方案,更改Bond_Portfolio类的内容. LPVOID arg确定每个线程要考虑的方案的分区. LPVOID arg也可以获取Bond_Portfolio的副本,在这种情况下,每个线程的计算将完全彼此独立.我该如何构建一个可以在类的私有部分中使用信息的线程函数?


The essential problem is that "bond_portfolio_thread_function" must be declared static and can no longer access the information of classes Scenarios[] and Bond_Portfolio. How can I proceed from here?

The facts are that scenario data do not change in the course of the simulation. The thread function is supposed to use the (fixed) scenario data for the evaluation of the bonds in Bond_Portfolio. The content of Class Bond_Portfolio is changed for each scenario. LPVOID arg determines the partition of Scenarios to be considered per thread. LPVOID arg could also take a copy of Bond_Portfolio, in which case the calculation per thread would be entirely independent of each other. How can I build a thread function which can use the information in the private part of the class? If not possible, which is the way around the problem?

推荐答案

您可以为该线程做一个小的包装,以方便进行线程处理:
我们不能在类的成员函数中使用线程吗? [
You can make a small wrapper to the thread, for easy threading:
Can''t we use threads inside the member function of class?[^]


A线程函数应该是静态的.因此,我们无法从线程函数访问非静态成员.

我们可以通过将类实例的地址传递给线程函数来解决此问题.在线程函数中,我们将其转换为类对象的实例,并可以调用该类的成员函数.

A thread function should be static. Therefore we cannot access the non-static members from the thread function.

We can solve this issue by passing address of class instance to the thread function. In thread function, we will convert it to an instance of class object and can call member functions of the class.

class MyClass
{
   struct THREAD_INFO
   {
      MyClass* pInstance;
      int      nScenarioToStart; // Information to a thread.
      .... // Add additional information for a thread.
   }
   UINT ThreadFunc( LPVOID pInstance )
   {
        THREAD_INFO* pThreadInfo = (THREAD_INFO*)pInstance;
        pThreadInfo->pInstance->ThreadImpl(pThreadInfo); // Calling member function from thread.
        return 1;
   )

   void ThreadImpl(THREAD_INFO* pThreadParam)
   {
     // pThreadParam holds parameters for each threads.
     // Actual thread implementation.
     // It is important to synchronize the access to class members by different threads.
   }
}


我建​​议使用以下方法:

将线程包装在类中(将其称为ThreadWrapper,在某些情况下(用于创建线程的非静态)函数),将"this"作为静态函数bond_portfolio_thread_function的参数LPVOID arg传递在此函数中,您需要将LPVOID强制转换为ThreadWrapper *.这样,您就可以从线程主体的实现中访问此包装器类的所有成员.通过显式传递access-to-the-instance参数(隐式传递为实例函数的隐藏参数)来通过实例函数访问实例成员,从而使此静态函数的行为类似于实例.

(为什么在OS API中不使用此方法,而该API允许将实例函数用作线程启动函数?仅因为这些OS基于遗留代码(并且面向对象不够")和OS API可以被C语言和其他非OOP语言使用.在真正的面向对象的平台(例如.NET,CLI)中,线程启动方法可以是非静态的.)
但是,您应该注意不要直接访问此ThreadWrapper实例的实例成员.由于这些成员成为共享访问权限的问题,因此您需要不直接提供访问权限,而是通过某些函数使用适当的线程同步原语(关键部分,互斥锁...)包装对成员的访问权限.这是基于线程包装器的方法的另一个好处:您可以使用类将代码中的那些同步原语完全隐藏,是的,可以确保访问线程的安全性.

—SA
I would suggest the following method:

Wrap the thread in the class (let''s call it ThreadWrapper, and in some instance (non-static) function used to create a thread, pass "this" as a parameter LPVOID arg of the static function bond_portfolio_thread_function. In this function, you will need to cast LPVOID to ThreadWrapper *. This way, you will get access to all members of this wrapper class from the implementation of the thread body. In a way, you will imitate the mechanism of getting access to the instance members by instance functions, by explicit passing of the access-to-the-instance parameter, which is passed implicitly as a hidden parameter of instance function. This way, you make this static function behaving like an instance one.

(Why this method is not used in OS APIs which would allow using instance functions as the thread start functions? Only because those OS are based on legacy code, which is "not object-oriented enough" and OS API can be uses by C and other non-OOP languages. In true object-oriented platforms (example: .NET, CLI), a thread start method can be non-static.)
However, you should be careful not to provide direct access to the instance members of this instance of ThreadWrapper. As those members becomes a matter of shared access, so you need to provide access not directly, but via some functions wrapping access to the members using appropriate thread synchronization primitives (critical section, mutex…). This is yet another benefit of the thread wrapper based approach: you can totally hide those synchronization primitives from the code using of the class, yes making access thread safe.

—SA


这篇关于静态成员函数和线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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