#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
答案 0 :(得分:0)
看起来你几乎不会对你抛出的所有线程原语感到困惑。
首先,您混合了不少于3种不同级别的线程抽象:
WaitForMultipleObjects
,事件)即便如此,你得到了大部分内容......混合起来:
您使用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