7

我对 boost::threads 很陌生,我阅读了文档,但在实践中应用它时遇到了一些麻烦,也许你可以帮忙?首先,我花时间编写了一个自包含的代码清单,演示了我尚无法理解的 2 种类型的行为......

该程序允许用户发出 3 个不同的命令,

  • 任务名称]
  • 信息
  • 退出

目的是该任务将在新线程上启动一些工作,然后在执行工作时返回到命令提示符。用户可以通过info命令找出哪些任务已完成,哪些尚未完成。

我使用的是双核 Win7 机器和 Visual Studio 2008 Express。

问题1>

发出命令task p1 p2 p3开始运行 3 个任务。这可以通过发出info来检查。几秒钟后工作完成,但由于某种原因,完成标志并不总是在 1 或 2 个任务上设置为真。

问题2>

退出程序然后会产生以下消息:

Windows 在 example.exe 中触发了一个断点。这可能是由于堆损坏,这表明 example.exe 或其已加载的任何 DLL 中存在错误。这也可能是由于在 example.exe 具有焦点时用户按 F12。输出窗口可能有更多诊断信息。

希望您可以重现此行为并提供帮助。

提前致谢。亚历克斯。

    //WARNING: THIS CODE DOES NOT BEHAVE EXACTLY AS INTENDED
#include <iostream>  
#include <string>
#include <sstream>
#include <boost/thread.hpp>  

using namespace std;

class task {
public:
    string mname;
    bool completed;
    void start()
    {
        int a = 0;
        for (int i=0 ; i<10000; i++)
        {
            for (int j=0 ; j<100000; j++)
            {
                a= i*2;
            }
        }
        this->completed = true;
    }
    task(string name)
    {
        mname = name;
        completed = false; 
    }
};

class taskManager{
    public:
        boost::thread_group threads;
        void startTask( string name )
        {
            //add new task to vector list           
            mtasks.push_back( task(name) );
            // execute start() on a new thread
            threads.create_thread( boost::bind( &task::start, &mtasks.back()) );
        }
        int tasksTotal()
        {
            return mtasks.size();
        }
        string taskInfo(int i)
        {
            string compstr("Not Completed");
            if ( mtasks[i].completed == true )
            {
                compstr = "Completed";
            }
            return mtasks[i].mname + " " + compstr; 
        }
    private:
        vector<task> mtasks; 
};

int main(int argc, char* argv[])  
{
    string cmd, temp;
    stringstream os;
    bool quit = false;
    taskManager mm;

    cout << "PROMPT>";

    while (quit == false)
    {
        //Wait for a valid command from user
        getline(cin,cmd);

        // Reset stringstream and assign new cmd string
        os.clear(); 
        os << "";
        os << cmd;
        //parse input string
        while (os >> temp) 
        {               
            if ( temp.compare("task") == 0 )
            {
                while (os >> temp) { mm.startTask( temp ); }                     
            }
            if ( temp.compare("info") == 0 )
            { 
                // Returns a list of all completed and not completed tasks
                for (int i = 0; i<mm.tasksTotal(); i++)
                {
                    cout << mm.taskInfo(i).c_str() << endl;
                }                           
            }
            if ( temp.compare("quit") == 0 ){ quit = true; }
        }

        cout << "PROMPT>";
    }

    mm.threads.join_all();      

    return 0;  
};
4

1 回答 1

4

方法中的代码有问题taskManager::startTask

mtasks.push_back( task(name) );
// execute start() on a new thread
threads.create_thread( boost::bind( &task::start, &mtasks.back())

这里的问题是,在推回一项新任务时,您的向量可能必须重新分配一些空间,从而使对旧向量元素的引用无效,例如以下调用taskinfo将引用错误的元素。当您删除旧元素时,您的堆会以某种方式损坏。

一个简单的解决方法是在类的构造函数中为向量保留一些空间taskManager,但是您可能应该更改任务/任务管理器模型的设计。另一种方法是使用 a std::deque,因为它不会重新分配内存。

于 2012-04-29T15:41:44.783 回答