30个线程,300个任务要执行,同时每个线程只能执行一个任务,怎么做?

sb3day 2010-03-27 02:09:22
queue<int> m_queueThread;//任务列表
//30个线程,300个任务要执行,同时每个线程只能执行一个任务
//全部执行完后等待5秒后全部任务重新开始,直到用户发送命令终止
#include <windows.h>
#include <vector>
#include <queue>

using namespace std;
HANDLE hSemaphore;
const int NUM_TASK=300;//总任务数
const int NUM_THREAD=30;//开启线程数n个
const int NUM_WAIT=5*1000;//任务全部结束后隔n秒后,重新开始
static bool b_stop=true;
CRITICAL_SECTION m_cs;
HANDLE hEvent;
static int si_thr;//任务序号

/************************
*线程
*
*************************/
unsigned long __stdcall ThreadFunc(void* lpParam)
{
queue<int>* q_Thred=(queue<int>*)lpParam;

while(b_stop)
{
EnterCriticalSection(&m_cs);
if(q_Thred->empty())//队列为空,任务全部完成
{
printf("开始等待\n");
printf("正在等待...\n");
DWORD dwWaritRes=WaitForSingleObject(hEvent,NUM_WAIT);
switch(dwWaritRes)
{
case WAIT_OBJECT_0:
printf("遇到事件结束等待\n");
//break;
case WAIT_TIMEOUT:
printf("等待结束!\n");
b_stop=0;
break;
break;
}

}
int i_newNum=q_Thred->front();
q_Thred->pop();//取出队列,已完成该任务
LeaveCriticalSection(&m_cs);

DWORD dwWaitResult;

dwWaitResult = WaitForSingleObject(
hSemaphore, // handle to semaphore
INFINITE); // zero-second time-out interval

switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
printf("%3d:正在执行任务%3d\n",si_thr++,i_newNum);//(*q_Thred).front());
break;

// Semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("%3d:TIMEOUT!!!!!!!!!!!!!!!!!!!!",si_thr++);
break;
}

if (!ReleaseSemaphore(
hSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
}
return 0;
}
bool Start(void)
{
hSemaphore = CreateSemaphore(
NULL, // default security attributes
NUM_THREAD, // initial count
NUM_THREAD, // maximum count
NULL); // unnamed semaphore

if (hSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
}

//std::vector<int> m_queueThread;//
queue<int> m_queueThread;//任务列表


for(int i=1;i<=NUM_TASK;i++)
{
m_queueThread.push(i);
}


DWORD ThreadID;
for(int i=0;i<NUM_THREAD;i++)
{
HANDLE handle=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFunc,
&m_queueThread,
0,
&ThreadID);
SetThreadPriority(handle,THREAD_PRIORITY_IDLE);
}
return true;
}
int main()
{
int nRetCode = 0;
InitializeCriticalSection(&m_cs);
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
si_thr=0;
if(Start())
printf("结束!\n");

{
// SetEvent(hEvent);
}
//DeleteCriticalSection(&m_cs);
return nRetCode;
}


如题:30个线程,300个任务要执行,同时每个线程只能执行一个任务
全部执行完后等待5秒后全部任务重新开始,直到用户发送命令终止
我这么写有错误,还有什么好的方法?
...全文
530 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
handyforever 2010-03-28
  • 打赏
  • 举报
回复
大哥大姐我已经没分了,只能在这里碰碰运气了,希望楼主不要怪罪于我,我有个捆饶我好几天的问题:我用函数调用了一个DLL,进入DLL后的界面里添加按钮,点击按钮调用了一个对话框,而当我在这个对话框上用了ADO和DATAGIRD控件后这个对话框就不能显示了,怎么解决?
我在EXE操作的时候是可以的,能调用,为什么用DLL就不成功了?
救救我吧!!!!!!!!!
leechrockgames 2010-03-28
  • 打赏
  • 举报
回复
你有个地方:for(int i;i<NUM_THREAD;i++)
CloseHandle(m_phThreads[i]);

应该是:
for(int i=0;i<NUM_THREAD;i++)
CloseHandle(m_phThreads[i]);

sb3day 2010-03-28
  • 打赏
  • 举报
回复
//30个线程,300个任务要执行,同时每个线程只能执行一个任务
//全部执行完后等待5秒后全部任务重新开始,直到用户发送命令终止
#include <windows.h>
#include <assert.h>
#include <queue>
#include <time.h>

using namespace std;
HANDLE hSemaphore;
const int NUM_TASK=135;//总任务数
const int NUM_THREAD=13;//开启线程数n个
const int NUM_WAIT=3*1000;//任务全部结束后隔n秒后,重新开始
CRITICAL_SECTION m_cs;
HANDLE hEvent;
int si_thr=1;//任务序号
static int i_thread=1;
unsigned long __stdcall ThreadFuncMain(void* lpParam);//主线程
unsigned long __stdcall ThreadFuncChild(void* lpParam);//子线程


/************************
*主线程
*
*************************/
unsigned long __stdcall ThreadFuncMain(void* lpParam)
{
bool b_Working=true;
while(b_Working)
{
printf("\n开始了!\n");
si_thr=1;
queue<int> m_queueThread;//任务列表
// m_queueThread.clear();
assert(m_queueThread.empty());

for(int i=1;i<=NUM_TASK;i++)
{
m_queueThread.push(i);
}


DWORD ThreadID;
PHANDLE m_phThreads;
m_phThreads = new HANDLE[NUM_THREAD];
for(int i=0;i<NUM_THREAD;i++)
{
m_phThreads[i]=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFuncChild,
&m_queueThread,
0,
&ThreadID);
SetThreadPriority(m_phThreads[i],THREAD_PRIORITY_IDLE);
//
}
DWORD dwWr=WaitForMultipleObjects(NUM_THREAD,m_phThreads,true,INFINITE);
// if(dwWr==WAIT_OBJECT_0||dwWr==WAIT_TIMEOUT||dwWr==WAIT_FAILED||dwWr==WAIT_ABANDONED_0)//在这里错了,子线程没有全部完成任务??怎么改??
//{
printf("任务完成!\n");
DWORD dwWaritRes=WaitForSingleObject(hEvent,NUM_WAIT);
switch(dwWaritRes)
{
case WAIT_OBJECT_0:
printf("遇到事件结束等待\n");
b_Working=false;
break;
case WAIT_TIMEOUT:
printf("等待结束!\n");
break;
//break;
}
//}
for(int i;i<NUM_THREAD;i++)
CloseHandle(m_phThreads[i]);

delete []m_phThreads;
//delete m_queueThread;
printf("WaitForMultipleObjects任务完成!\n");

}
return 0;
}


/************************
*子线程
*
*************************/
unsigned long __stdcall ThreadFuncChild(void* lpParam)
{
queue<int>* q_Thred=(queue<int>*)lpParam;
//bool b_Work=true;
while(true)
{
EnterCriticalSection(&m_cs);
if(q_Thred->empty())//队列为空,任务全部完成//size()==0)//
{
LeaveCriticalSection(&m_cs);
//b_Work=false;
break;
}
int i_newNum=q_Thred->front();
q_Thred->pop();//取出队列,已完成该任务

printf("%3d:正在执行任务%3d\n",si_thr++,i_newNum);//(*q_Thred).front());
LeaveCriticalSection(&m_cs);
srand((unsigned)time(0));
int x=(rand()*si_thr)%500;
Sleep(x);
printf("\t\t\t睡眠%d秒后结束\n",x);
//
}
printf("结束一个子线程%d\n",i_thread++);
return 1;
}

/**********************************
*开启主线程
*
**********************************/
bool Start(void)
{
HANDLE hHandel=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFuncMain,
NULL,
0,
NULL);
WaitForSingleObject(hHandel,INFINITE);
printf("开启主线程!\n");
return true;
}


int main()
{
//if(getchar()==(int)"a")
//{
// printf("yes");
// SetEvent(hEvent);
//}

int nRetCode = 0;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
si_thr=0;
InitializeCriticalSection(&m_cs);
if(Start())
printf("结束!\n");
DeleteCriticalSection(&m_cs);


return nRetCode;
}
现在这个才是对的,原来LeaveCriticalSection(&m_cs);写错地方了
sb3day 2010-03-28
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 leechrockgames 的回复:]
你有个地方:for(int i;i<NUM_THREAD;i++)
CloseHandle(m_phThreads[i]);

应该是:
for(int i=0;i<NUM_THREAD;i++)
CloseHandle(m_phThreads[i]);
[/Quote]这一样的吧,我在vs2005下调试了,初始值自动是0
zxdyu2009 2010-03-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sb3day 的回复:]
还有个问题:用户输入回车键,结束全部任务,这个要怎么做??在main()里写getchar()==多少吗,但是这样在主线程没有退出是不会执行到的
[/Quote]
主线程应该有循环动作才对啊,这样不就可以判断有没有按键按下。再说你主线程一下子就跑了,别的线程有可能没有完成,就迫使退出了。
sb3day 2010-03-27
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 jiaxing1208 的回复:]
多线程执行“一堆”任务,这个任务堆就是一个全局数据,线程内操作全局数据最重要的是“同步”。
两种设计方案:
一,让任务堆放到一个独立的工作线程中(注意不是主线程),各个执行任务的线程中各设一个状态标签,线程每次执行完分配到的一个任务的时候,都先设置一下该状态标签,表明自己准备“进入分配任务等待”状态,然后利用同步对象进入等待中;任务堆所在的那个工作线程的任务就是不断遍历这些线程的状态标签,发现……
[/Quote]谢谢啊,感觉好抽象啊,呵呵,和看代码一样难
sb3day 2010-03-27
  • 打赏
  • 举报
回复
还有个问题:用户输入回车键,结束全部任务,这个要怎么做??在main()里写getchar()==多少吗,但是这样在主线程没有退出是不会执行到的
sb3day 2010-03-27
  • 打赏
  • 举报
回复
//30个线程,300个任务要执行,同时每个线程只能执行一个任务
//全部执行完后等待5秒后全部任务重新开始,直到用户发送命令终止
#include <windows.h>
#include <assert.h>
#include <queue>

using namespace std;
HANDLE hSemaphore;
const int NUM_TASK=333;//总任务数
const int NUM_THREAD=44;//开启线程数n个
const int NUM_WAIT=3*1000;//任务全部结束后隔n秒后,重新开始
CRITICAL_SECTION m_cs;
HANDLE hEvent;
int si_thr=1;//任务序号

unsigned long __stdcall ThreadFuncMain(void* lpParam);//主线程
unsigned long __stdcall ThreadFuncChild(void* lpParam);//子线程


/************************
*主线程
*
*************************/
unsigned long __stdcall ThreadFuncMain(void* lpParam)
{
bool b_Working=true;
while(b_Working)
{
printf("\n开始了!\n");
InitializeCriticalSection(&m_cs);
si_thr=1;
queue<int> m_queueThread;//任务列表
// m_queueThread.clear();
assert(m_queueThread.empty());

for(int i=1;i<=NUM_TASK;i++)
{
m_queueThread.push(i);
}


DWORD ThreadID;
PHANDLE m_phThreads;
m_phThreads = new HANDLE[NUM_THREAD];
for(int i=0;i<NUM_THREAD;i++)
{
m_phThreads[i]=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFuncChild,
&m_queueThread,
0,
&ThreadID);
SetThreadPriority(m_phThreads[i],THREAD_PRIORITY_IDLE);
}
//DWORD dwWr=
WaitForMultipleObjects(NUM_THREAD,m_phThreads,false,INFINITE);
//if(dwWr==WAIT_OBJECT_0||dwWr==WAIT_TIMEOUT)//在这里错了,子线程没有全部完成任务??怎么改??
//{
printf("任务完成!\n");
DWORD dwWaritRes=WaitForSingleObject(hEvent,NUM_WAIT);
switch(dwWaritRes)
{
case WAIT_OBJECT_0:
printf("遇到事件结束等待\n");
b_Working=false;
break;
case WAIT_TIMEOUT:
printf("等待结束!\n");
DeleteCriticalSection(&m_cs);
break;
//break;
}
//}

}
return 0;
}


/************************
*子线程
*
*************************/
unsigned long __stdcall ThreadFuncChild(void* lpParam)
{
queue<int>* q_Thred=(queue<int>*)lpParam;

while(true)
{
EnterCriticalSection(&m_cs);
if(q_Thred->empty())//队列为空,任务全部完成
{
break;
}
int i_newNum=q_Thred->front();
q_Thred->pop();//取出队列,已完成该任务

printf("%3d:正在执行任务%3d\n",si_thr++,i_newNum);//(*q_Thred).front());
LeaveCriticalSection(&m_cs);
Sleep(500);
// printf("%3d:睡眠结束\n",si_thr);

}
return 0;
}

/**********************************
*开启主线程
*
**********************************/
bool Start(void)
{
HANDLE hHandel=CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadFuncMain,
NULL,
0,
NULL);
WaitForSingleObject(hHandel,INFINITE);
printf("开启主线程!\n");
return true;
}


int main()
{
int nRetCode = 0;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
si_thr=0;
if(Start())
printf("结束!\n");

{
// SetEvent(hEvent);
}
return nRetCode;
}

谢谢大家,听了oyljerry的方法,主线程控制30个子线程循环执行300个任务;
问题解决了,哈哈!
biganchor 2010-03-27
  • 打赏
  • 举报
回复
多线程执行“一堆”任务,这个任务堆就是一个全局数据,线程内操作全局数据最重要的是“同步”。
两种设计方案:
一,让任务堆放到一个独立的工作线程中(注意不是主线程),各个执行任务的线程中各设一个状态标签,线程每次执行完分配到的一个任务的时候,都先设置一下该状态标签,表明自己准备“进入分配任务等待”状态,然后利用同步对象进入等待中;任务堆所在的那个工作线程的任务就是不断遍历这些线程的状态标签,发现“进入分配任务等待”状态的线程,即分配给它新的任务,然后“激活”它的等待对象...如果任务为空,则不激活,宣告任务全部完成;

二,让任务线程自己主动去取任务,把任务堆放在一个全部线程“够”得着的地方,分配任务的方法注意设置同步对象就行了,比如critical section,那实际上是把第一种方案的任务分配操作让给了任务线程本身去执行了。

第一种方案要有一个不断循环遍历的线程,感觉有点消耗cpu时钟;第二种有效解决第一种的缺陷,但是线程的职责没第一种划分的清晰了。

个人看法,供你参考了。
SullenSun 2010-03-27
  • 打赏
  • 举报
回复
喝了点酒,代码有点多,头晕了。。。
哈利路亚1874 2010-03-27
  • 打赏
  • 举报
回复
这个应该使用异步模式
oyljerry 2010-03-27
  • 打赏
  • 举报
回复
主线程要一直循环,等其他子线程执行,当你需要停止程序时,才通知所有子线程退出,然后主线程退出循环
fishion 2010-03-27
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zxdyu2009 的回复:]
主线程没有等待全部线程退出,就先走了。
[/Quote]

看你的代码是这样呀,呵呵,要主线程中加一个
while(true)
{
Sleep(1000);
}
zxdyu2009 2010-03-27
  • 打赏
  • 举报
回复
主线程没有等待全部线程退出,就先走了。
验证码识别 2010-03-27
  • 打赏
  • 举报
回复
找个专门搞线程管理的开源代码的,比自己写稳定多了

我记得是有这个的
sb3day 2010-03-27
  • 打赏
  • 举报
回复
M个任务,N个线程,一个线程在同一时间内只能执行一个任务,我是这么做的:
把任务列表保存到queue里,在线程里一运行一个任务就pop掉这个任务,当queue为空时就结束该线程

我写的代码不知为什么只执行几个任务就结束了,M个任务没有执行完
Eleven 2010-03-27
  • 打赏
  • 举报
回复
你直接说你除了出现了什么问题得了
bragi523 2010-03-27
  • 打赏
  • 举报
回复
是设计问题?还是你的代码有什么问题,说具体一点
fishion 2010-03-27
  • 打赏
  • 举报
回复
你是出了什么问题了?

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧