多个线程如何访问同一个控件,比如,每次开辟60个线程,往一个控件写入数据,等这60个线程结束,再开辟60个线程也往这个控件写数据。代码如下,当开辟的线程总共超过950个时程序便处于“死机状态”了。不知为什么CCriticalSection Section;
volatile int iCounter=0;UINT threadA(LPVOID pParam)
{
CxxxDlg *threada=(CxxxDlg*)pParam;
Section.Lock();
int IpPort = iCounter;

iCounter++;
::PostMessage(threada->GetSafeHwnd(),WM_USER_RECALC_DONE,IpPort,0);
Section.Unlock();
return 0;}
void CxxxDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
m_list.ResetContent();
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
UpdateData(TRUE);
int v;
if(m_Eport == m_Sport)//m_Eport m_Sport 都是int类型,例如//m_Sport=0,m_Eport=950;
v = 1;
else
{
v = (m_Eport-m_Sport)/60;
if( ( (m_Eport-m_Sport)%60 ) > 0 )
v++;
}
HANDLE hThread[61];
CWinThread *pT[61];
iCounter        = m_Sport;
//创建线程
for(int i=0;i<v;i++){
int a=0;
for(int k=0;k<60;k++)
{
a++;
if(iCounter>=m_Eport)
break;
pT[k]=AfxBeginThread(threadA,this);

hThread[k]=pT[k]->m_hThread;
}
WaitForMultipleObjects(a,hThread,TRUE,INFINITE);
}
GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);}
LRESULT  CxxxDlg::OnRecalcDone(WPARAM wParam, LPARAM lParam)
{
int a=(int)wParam;
char bb[10];
memset(bb,0,10);
itoa(a,bb,10);
m_list.AddString(bb);
return 0;}
把PostMessage换成SendMessage()总共开辟两三个线程程序便处于死机状态,比如m_Sport=0,m_Eport=3;不知为什么

解决方案 »

  1.   

    因为SendMessage是同程的,要等到主线程响应后才返回,但你的主线程看来是没法响应了,一直在WaitForMultipleObjects(a,hThread,TRUE,INFINITE);就这代码,你就只起动一个线程,只要线程中有SendMessage程序会死锁.
      

  2.   

    谢谢tryber(cyber)   我明白了
    第一个问题“当开辟的线程总共超过950个时程序便处于“死机状态”了”应该怎么解决
      

  3.   

    我也不知为什么,而我用你的代码在我的机器上工作的好好的,尽管有点改动,但很明显你的a++这么放较合理.CCriticalSection Section;
    volatile int iCounter=0;
    UINT Athread(LPVOID lparam)
    {
    Section.Lock();
    int IpPort = iCounter;
    iCounter++;
    PostMessage((HWND)lparam,WM_USER+10,0,0);
    Section.Unlock();
    return 0;
    }
    void CMainFrame::OnStart()
    {
    // TODO: 在此添加命令处理程序代码
    HANDLE hThread[61];
    CWinThread *pT[61];
    //创建线程
    for(int i=0;i<20;i++){
    int a=0;
    for(int k=0;k<60;k++)
    {
    if(iCounter>=950)
    break;
                         pT[k]=NULL;
                         hThread[k]=NULL; pT[k]=AfxBeginThread(Athread,(LPVOID)GetSafeHwnd());
    if(pT[k]!=NULL)
                        {
                                a++;
    hThread[k]=pT[k]->m_hThread;
                         }
    }
    WaitForMultipleObjects(a,hThread,TRUE,INFINITE);
    }
      

  4.   

    tryber(cyber)不知道你的测试程序有没有往控件写数据这一步骤。如果有这个步骤的话当开辟的线程数大于1000时(for(int i=0;i<15;i++))程序长时间处于死机状态,然后提示系统资源不足。可能是有些资源没释放掉,但哪些资源没释放掉我就不知道了。当去掉PostMessage((HWND)lparam,WM_USER+10,0,0);这一句时(不往控件写数据)程序运行正常。
    你的操作系统是不是2000的或XP 我的是98的
      

  5.   

    "开辟的线程数大于1000",我不知道你指的线程数是什么,从这代码来看
                      for(int k=0;k<60;k++)
    {
    if(iCounter>=950)
    break;
                         pT[k]=NULL;
                         hThread[k]=NULL; pT[k]=AfxBeginThread(Athread,(LPVOID)GetSafeHwnd());
    if(pT[k]!=NULL)
                        {
                                a++;
    hThread[k]=pT[k]->m_hThread;
                         }
    }
    WaitForMultipleObjects(a,hThread,TRUE,INFINITE); //nobig60
    这会让程式任何时刻所有的线程数不会超过60个,行nobig60会等到这a个线程都退出后才启动下a个,但是每次这a个线程都往目标窗口发一个消息后退出,以致于你点按钮后,目标窗口要响应那么多次(发送的消息数大于1000),要加1000个item,如果有sort风格还要排序,更新视图...当然慢了.我不知你做的是什么,要是我的话,我会边启动线程边处理消息,比如让等待动作放在消息处理函数中,这样才真正达到多线程的目的.如果你非要这么做的话,建议在启动线程前用对CListBox实行InitStorage(..),一定对程序的性能大有提高,详见msdn.
      

  6.   

    其实,我想提高程序速度,比如说总共要开辟120个线程,每个线程都执行不同的代码(通过iCounter可以看出)先开辟60个线程,先让这60个线程运行,运行完毕,再开辟下60个,这种方法是不是比开辟完一个线程,此线程运行完毕再开辟下一个线程的方法速度快?上面说的“开辟的线程数大于1000”是指总的线程数。