想要在变量达到某个值

时间:2015-09-28 09:48:07

标签: c++ boost

#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
using namespace std;

#define MAX_THREAD_COUNT 50

class A
{
public:
    static void ExecDecrementX(void* thisObj, int *x)
    {
        cout << "DecrementX thread..." << endl;
        A *obj = (A*)thisObj;
        obj->DecrementX(x);
    }

    void DecrementX(int* x)
    {
        cout << "Thread Instantiated........" << endl;
        for (; *x <= 1200; (*x)++)
        {
            cout << "DecrementX thread, X = " << *x << endl;
            if (*x == 1100)
            {
                HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, L"MyEvent1");
                if (!hEvent) { return; }
                ResetEvent(hEvent);
                if (SetEvent(hEvent))
                {
                    cout << "Got The signal - MyEvent 1......." << endl;
                    CloseHandle(hEvent);
                }
            }
        }
        cout << "End of the Thread ......" << endl;
    }
};

int main()
{
    int x = 1000;
    A* obj1 = new A();
    DWORD dwRet;
    HANDLE Events_Handle[1];
    HANDLE  hEvent1 = CreateEvent(NULL, true, false, L"MyEvent1");
    if (!hEvent1) return -1;
    Events_Handle[0] = hEvent1;
    void(*fPtr)(void*, int*) = A::ExecDecrementX;
    boost::asio::io_service ioService;
    boost::thread_group ThreadPool;
    boost::asio::io_service::work work(ioService);
    for (int threadcount = 0; threadcount < MAX_THREAD_COUNT; threadcount++)
    {
        ThreadPool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
    }
    cout << "Main thread\n";
    ioService.post(boost::bind(fPtr, obj1, &x));
    while (1)
    {
        dwRet = WaitForMultipleObjects(1, Events_Handle, false, INFINITE);
        cout << "dwRet = " << dwRet << endl;
        if (dwRet == WAIT_OBJECT_0)
        {
            cout << "All events were signaled..." << endl;
            ioService.stop();
            ThreadPool.interrupt_all();
            cout << "Remaining threads interrupted... X = " << x << endl;
            CloseHandle(hEvent1);
            break;
        }
    }
    cout << "Main Thread: At the End X = " << x << endl;
    return 0;
}

我的要求是一旦x达到1100,中断了所有线程,但即使在线程池中断之后,我看到线程池继续并继续打印直到结束。 你能帮我理解发生了什么,我该如何解决?

谢谢, JK

1 个答案:

答案 0 :(得分:0)

看起来你几乎不会对你抛出的所有线程原语感到困惑。

首先,您混合了不少于3种不同级别的线程抽象:

  • Asio异步任务排队
  • 提升线程可移植线程库(thread_group和中断点)
  • Windows原生API(WaitForMultipleObjects,事件)

即便如此,你得到了大部分内容......混合起来:

  • 事件是一个命名对象。也就是说,它用于进程间同步(IPC),并且所有实例都是同一个同步对象的不同内核句柄......
  • 您使用WaitForMultipleObjects等待... 1个固定同步对象。似乎你可以做得更好:)

  • 使用interrupt_all()意味着您使用中断点然而您从未处理thread_interrupted例外?请参阅文档:http://www.boost.org/doc/libs/1_59_0/doc/html/thread/thread_management.html#thread.thread_management.tutorial.interruption

  • 您似乎使用Boost Asio来为线程池上的任务提供服务。 然而您只需将1个任务发布到服务中,这意味着在运行任务时不会超过1个线程。

      

    混淆的关键来源似乎是任务 线程

         

    池管理线程,服务juggles 任务。你的“任务”似乎有雄心占据一个完整的线程。这绝对不适合线程池(整个想法是为多个短期任务重用相同的线程)和特别是异步处理(长时间运行的任务阻塞队列而没有任何内容)异步将在同一个线程上发生。)

  • 使用work是错误的。它的生命周期未设置为在连接之前结束,这意味着io_service::run操作永远不会返回。见docs

      

    工作类用于在工作开始和结束时通知io_service。这可以确保io_service对象的run()函数在工作正在进行时不会退出,并确保在没有剩余未完成的工作时退出。

  • 最后,为什么在Asio任务队列中需要50个线程。只有在 CPU绑定的长时间运行任务时才有意义。这与异步任务处理完全相反。

  • 具有讽刺意味的是,DecrementX似乎除了增量 x之外别无其他。应该在互斥锁下访问哪个。我把它设为atomic_size_t

这是一次谦卑的清理尝试:

<强> Live On Coliru

#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <iostream>

class A {
    boost::atomic_size_t x { 0 };
    boost::asio::io_service& _svc;

public:
    A(boost::asio::io_service& svc) : _svc(svc) {}
    void IncrementX() {
        std::cout << "IncrementX X = " << x << "\n";
        if (x++ == 1100)
            _svc.stop();
    }

    size_t getX() const { return x; }
};

int main()
{
    using namespace boost;

    asio::io_service ioService;
    A obj(ioService);

    thread_group pool;
    optional<asio::io_service::work> work = asio::io_service::work(ioService);

    for (unsigned i = 0; i < thread::hardware_concurrency(); i++) {
        pool.create_thread(bind(&asio::io_service::run, &ioService));
    }

    std::cout << "Main thread\n";

    while (!ioService.stopped())
    {
        ioService.post(bind(&A::IncrementX, &obj));
    }

    work.reset();
    pool.join_all();

    std::cout << "Main Thread: At the End X = " << obj.getX() << std::endl;
}

打印(缩减):

Main thread
IncrementX X = IncrementX X = 00

IncrementX X = IncrementX X = 2
2
IncrementX X = IncrementX X = 4
4
IncrementX X = 5
IncrementX X = 7IncrementX X = 
7
IncrementX X = IncrementX X = 99

IncrementX X = IncrementX X = 1111

IncrementX X = 13
IncrementX X = 14
IncrementX X = 15
IncrementX X = 16
IncrementX X = 17
IncrementX X = 18
IncrementX X = 19
IncrementX X = 20
IncrementX X = 21
...
...
IncrementX X = 1078IncrementX X = 
1074
IncrementX X = 1079
IncrementX X = 
IncrementX X = IncrementX X = IncrementX X = 1082
10751081

IncrementX X = IncrementX X = 10851085

IncrementX X = 10811085IncrementX X = 
1087IncrementX X = IncrementX X = 1088
IncrementX X = 1089
IncrementX X = 1090
IncrementX X = 1091

IncrementX X = 1092
IncrementX X = 1093

1087IncrementX X = 
1095IncrementX X = IncrementX X = 1096

1097
IncrementX X = IncrementX X = 1097
1100
IncrementX X = IncrementX X = 11021102



IncrementX X = 1075

Main Thread: At the End X = 1108

real    0m0.003s
user    0m0.000s
sys 0m0.006s