带继承的多线程 (C++)

Posted

技术标签:

【中文标题】带继承的多线程 (C++)【英文标题】:Multithreading with Inheritance (C++) 【发布时间】:2009-05-15 16:30:37 【问题描述】:

我正在尝试在新线程中调用“运行”函数。现在,我使用 openMP 的这段代码实际上并没有在新线程中运行“运行”。注意:我不是在寻求使用 OpenMP 的帮助。这段代码只是一个快速修复。我更喜欢 CreateThread() 方法来解决这个问题。

vector<ICommand*>* commands;
string strInput;
// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)

    // ...if the current command we're examining is valid...
    if((*i)->ContainsCommand(strInput))
    
        // ...run it in a new thread and don't let ZChatInput handle it normally...
        #pragma omp sections nowait
        
        #pragma omp section
            (*i)->Run(strInput);
        #pragma omp section
            bRet = false;
        

        // ...and don't check any more commands.
        break;
    


那么如何仅使用标准和 STL 来完成呢?当然,我正在寻找一种可行的方法:)

【问题讨论】:

【参考方案1】:

使用 Boost.Thread 怎么样?

if((*i)->ContainsCommand(strInput))

    boost::thread t( boost::bind( &ICommand::Run, *i ) );

这将在一个分离的线程中运行“运行”。 (注意,我没有对此进行测试。)

【讨论】:

不,抱歉。我试图回避 3rd 方库。如果VS2010有这个功能,那我试试;但在那之前,仍然不是我想要的。此外,您忘记将 strInput 作为参数传递。 boost 有什么问题?它几乎和 stl 一样标准。很多boost库都进入了新标准,如果boost线程成为新标准我不会印象深刻(我知道线程有一个新标准,但我不知道它们是否类似于boost线程型号) C++0x 将具有类似于 boost.thread 的线程工具。见en.wikipedia.org/wiki/C%2B%2B0x#Threading_facilities 谢谢你,但这与我的问题无关。我仍在寻找 WinAPI 解决方案。 任何线程库最终都会使用 OS API,所以将其视为包装器。【参考方案2】:

喜欢这样吗? http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx

【讨论】:

类似于 boost 示例,您使用指向函数的指针作为参数,然后向上运行。 _beginthread 和 CreateThread 是多线程的 MS 函数 int h = (HANDLE)_beginthreadex(NULL,0,(*i)->Run,&strInput,0,NULL);不完全确定,并且 Run 必须是一个 _stdcall 函数。这是一个win32 api 这是 __stdcall... 我所有的功能都是。我会尝试一下,但是隐含的“this”指针呢?您没有将其作为参数传递。 对不起,我不知道你在说什么“this”指针。我已经从一个类中使用它来启动一个事件处理程序,并将“this”作为参数参数传递 _beginthreadex(NULL,0,function,this,0,NULL) 然后让“函数”成为我班级的朋友。我在以这种方式运行类成员函数时遇到了一些困难,所以也许这不是你要找的机器人。【参考方案3】:

你可以试试这样的:

vector<ICommand*>* commands;
string strInput;

void CommandOnThread(void* command)

    (ICommand*)command->Run();


// For each command...
for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)

    // ...if the current command we're examining is valid...
    if((*i)->ContainsCommand(strInput))
    
        //Attach the input to the command
        (*i)->AttachInput(strInput);
        _beginthread(CommandOnThread, 0, *i);
        break;
    

为此,您必须稍微更改命令接口,以便分两步传递命令输入:首先将输入存储在命令对象中,然后不带参数调用 Run()。如果你喜欢它们非常相似,你可以用 CreateThread 替换 _beginthread。

澄清一下:您不能使用实例方法作为 _beginthread(或 CreateThread)的函数参数。上面的解决方案是将对象(命令)传递给函数,然后调用它的实例方法(运行)。但是在这种情况下,您不能将额外的参数传递给线程函数,因此不能将参数传递给实例方法。最简单的解决方案是在将参数传递给线程函数之前以某种方式将参数附加到实例。

我希望这会有所帮助。当然,如果不能更改 Command 类的接口和实现,这种解决方案是不可能的。

【讨论】:

“AttachInput”在哪里定义?此外,您没有将任何参数传递给 command->Run() 你必须自己定义。只能将一个参数传递给线程函数,并且它已经用于传递命令对象。【参考方案4】:

您真的要为每个命令创建一个线程吗?线程创建是昂贵的。 如果您绝对需要这部分是异步的 - 创建一个同步队列,预生成线程数(这是您的可伸缩性)让它们阻塞在队列中,然后将消息(指针?)放入循环中的队列中。

回答您的评论:

// 设置 同步队列 wq; // 这将受到互斥锁和一个或两个条件变量的保护 for ( i = 0; i

有道理吗?

【讨论】:

它不是为每个命令创建一个线程。如果输入有效,它只会创建线程,而不是更多。它必须是异步的,否则它会变得非常缓慢。我不明白你的实施策略。你能展示一些示例伪代码吗? 确实...但是对于一个简单的线程创建来说似乎需要做很多工作... CreateThread 或其他一些 WinAPI 必须有更好的方法。 您是否为每个有效输入调用 Run()?然后预先启动线程。否则你可能会发现它比单线程慢。而且,是的,搞乱线程是很多工作。 这里是 CreateThread 的 MSDN 文档的链接:msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx【参考方案5】:

所以我在仔细检查了 MSDN 文档后发现了这一点。以下是我的做法,如果你们有兴趣的话:

static vector<ICommand*>* commands;
// This is what we pass to CommandOnThread.
struct CommandParameter

    string strInput;
    ICommand* command;
;

int CommandOnThread(CommandParameter* cp)

    cp->command->Run(cp->strInput);
    delete cp;

    return 0;


void foo()

    string strInput;
    ...
    // For each command...
    for(vector<ICommand*>::iterator i = commands->begin(); i != commands->end(); ++i)
    
        // ...if the current command we're examining is valid...
        if((*i)->ContainsCommand(strInput))
        
            // Put the CP on the stack.
            CommandParameter* temp = new CommandParameter;
            if(temp == NULL)
            
                Print("Out of memory!");
                bRet = false;
                break;
            

            // ...set up the parameters to createthread...
            temp->strInput = strInput;
            temp->command = *i;

            // ...run it in a new thread...
            CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CommandOnThread, temp, NULL, NULL);

            // ...and don't check any more commands.
            bRet = false;
            break;
        
    

【讨论】:

以上是关于带继承的多线程 (C++)的主要内容,如果未能解决你的问题,请参考以下文章

多线程

Java多线程

带参数的多线程如何去写?

java多线程3种方式

带返回值的多线程

java多线程