怎样暂停(挂起)和恢复一个线程呢?

时间:2022-12-12 18:07:23
怎样在一个线程中暂停(挂起)和恢复另一个线程呢?
《WINDOWS核心编程》中说可以使用
DWORD SuspendThread ( HANDLE hThread );   //挂起线程
DWORD ResumeThread ( HANDLE hThread );   //恢复线程
是不是使用这两个函数就行?

比如我在int main()中创建了两个线程

handle[0]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,NULL,0,NULL);
handle[1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,NULL,0,NULL);

线程函数ThreadFunc1执行一个任务操作(比如循环写入0至9),而ThreadFunc2不断检测某个条件的是否满足,如果满足,则暂停线程1的任务操作,是不是这样写就行:
ThreadFunc2()
{
  if(条件满足)
    {
        SuspendThread(handle[0]);
        //报警声;
    }
}

10 个解决方案

#1


是不是?自己试试不就知道了吗 总共就2个API 有问的功夫早就试出来了

#2


对啊

你把它加入代码里面

如果参数没问题的画

逻辑上是可以通过的

#3


函数是对的。
你在ThreadFunc2中Suspend,得先确保thread1的线程函数这时候还没有退出。

#4


TO ydfivy
我其实也是这个疑问。那是不是还需要再建立一个同步事件?

#5


因为不太明白楼主的用意。所以不能轻易出主意。

如果你想让第一个线程挂起,你可以在创建线程后,就将其挂起。然后在第二个线程中Resume.

用不用同步,这个楼主按照自己的想法来决定吧。:)

#6


To ydfvy:
还是有问题。贴出我的代码,您看一下。按了“执行”后,程序运行起来,然后在记事本B中输入a后,记事本A中循环输入数字暂停,但无法点击“恢复线程1”的按钮,程序无响应,鼠标呈现一直在忙碌的状态...
注:以下代码中的dm1 dm2是个叫“大漠插件”的对象,就是绑定窗口后,可以对窗口内输入字符、找图等。

//第一个线程:向记事本A中不断写入0 1 2 3 4 5 6 7 8 9 
unsigned int _stdcall ThreadFunc1(void *pm1)
{
dm1.BindWindow(0x4b068e,"gdi","windows","windows",0);
Sleep(100);
int i=0;
while (true)
{
dm1.KeyPress(48+i%10);
Sleep(1000);
i++;
}
dm1.UnBindWindow();
return 0;
}
//第二个线程:每隔五秒,检测记事本B中是否出现了字母a,若出现了字母a,发出声音,并挂起线程1
unsigned int _stdcall ThreadFunc2(void *pm2)
{
VARIANT intXR,intYR,width,height;
dm2.SetPath("I:\\路径");
//绑定窗口
dm2.BindWindow(0x59063e,"gdi","windows","windows",0);
dm2.GetClientSize(0x59063e,&width,&height);
while(true)
{
Sleep(5000);
long   find_rwret=dm2.FindPic(0,0,width.lVal,height.lVal,"a.bmp","020202",1,0,&intXR,&intYR);
if(find_rwret>=0)
{
dm2.Play("allsuccess.wav");
::SuspendThread(handle[0]);
//退出检测
break;
}
}
dm2.UnBindWindow();
return 0;
}

//有两个按钮
//第一个按钮:"执行",开始执行线程1和线程2
void CDxcTestDmDlg::OnButton1() 
{
//线程1
handle[0]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,NULL,0,NULL);
//线程2
handle[1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,NULL,0,NULL);
WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);
}
//第二个按钮:“恢复线程1”
void CDxcTestDmDlg::OnButton2() 
{
ResumeThread(handle[0]);
}

#7


void CDxcTestDmDlg::OnButton1() 
{
    //线程1
    handle[0]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,NULL,0,NULL);
    //线程2
    handle[1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,NULL,0,NULL);
    WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);
}
这里的Wait函数在死等,界面线程已经停止响应了。你点不了Button2正常。

#8


WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);这个第三个参数改成FALSE。
这样Thread2退出,你的界面就能响应了。

#9


To ydfivy:
太对了,感谢!

不过我又有了一个新的问题。如果把线程函数2中的break注释掉,也就是说发现有字母a时(满足条件时),只是挂起线程1,但线程2仍继续循环检测(因为我可以把记事本B中的a手动删除掉),那么这样的话,线程2就永远退不出来,这样即使WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE)的第三个参数改成FALSE夜不好使了,那该怎么办呢??

//第二个线程:每隔五秒,检测记事本B中是否出现了字母a,若出现了字母a,发出声音,并挂起线程1
unsigned int _stdcall ThreadFunc2(void *pm2)
{
    VARIANT intXR,intYR,width,height;
    dm2.SetPath("I:\\路径");
    //绑定窗口
    dm2.BindWindow(0x59063e,"gdi","windows","windows",0);
    dm2.GetClientSize(0x59063e,&width,&height);
    while(true)
    {
        Sleep(5000);
        long   find_rwret=dm2.FindPic(0,0,width.lVal,height.lVal,"a.bmp","020202",1,0,&intXR,&intYR);
        if(find_rwret>=0)
        {
            dm2.Play("allsuccess.wav");
            ::SuspendThread(handle[0]);
//把break注释掉,也就是说发现有字母a时(满足条件时),只是挂起线程1,但线程2仍继续循环检测(因为我可以把记事本B中的a手动删除掉)
            //break;
        }
    }
    dm2.UnBindWindow();
    return 0;
}

#10


啊O,好复杂。
呵呵。
办法就是把现在做的这些再移动一个工作线程里。然后根据上边那两个线程的状态,设置按钮是disable还是enable.

#1


是不是?自己试试不就知道了吗 总共就2个API 有问的功夫早就试出来了

#2


对啊

你把它加入代码里面

如果参数没问题的画

逻辑上是可以通过的

#3


函数是对的。
你在ThreadFunc2中Suspend,得先确保thread1的线程函数这时候还没有退出。

#4


TO ydfivy
我其实也是这个疑问。那是不是还需要再建立一个同步事件?

#5


因为不太明白楼主的用意。所以不能轻易出主意。

如果你想让第一个线程挂起,你可以在创建线程后,就将其挂起。然后在第二个线程中Resume.

用不用同步,这个楼主按照自己的想法来决定吧。:)

#6


To ydfvy:
还是有问题。贴出我的代码,您看一下。按了“执行”后,程序运行起来,然后在记事本B中输入a后,记事本A中循环输入数字暂停,但无法点击“恢复线程1”的按钮,程序无响应,鼠标呈现一直在忙碌的状态...
注:以下代码中的dm1 dm2是个叫“大漠插件”的对象,就是绑定窗口后,可以对窗口内输入字符、找图等。

//第一个线程:向记事本A中不断写入0 1 2 3 4 5 6 7 8 9 
unsigned int _stdcall ThreadFunc1(void *pm1)
{
dm1.BindWindow(0x4b068e,"gdi","windows","windows",0);
Sleep(100);
int i=0;
while (true)
{
dm1.KeyPress(48+i%10);
Sleep(1000);
i++;
}
dm1.UnBindWindow();
return 0;
}
//第二个线程:每隔五秒,检测记事本B中是否出现了字母a,若出现了字母a,发出声音,并挂起线程1
unsigned int _stdcall ThreadFunc2(void *pm2)
{
VARIANT intXR,intYR,width,height;
dm2.SetPath("I:\\路径");
//绑定窗口
dm2.BindWindow(0x59063e,"gdi","windows","windows",0);
dm2.GetClientSize(0x59063e,&width,&height);
while(true)
{
Sleep(5000);
long   find_rwret=dm2.FindPic(0,0,width.lVal,height.lVal,"a.bmp","020202",1,0,&intXR,&intYR);
if(find_rwret>=0)
{
dm2.Play("allsuccess.wav");
::SuspendThread(handle[0]);
//退出检测
break;
}
}
dm2.UnBindWindow();
return 0;
}

//有两个按钮
//第一个按钮:"执行",开始执行线程1和线程2
void CDxcTestDmDlg::OnButton1() 
{
//线程1
handle[0]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,NULL,0,NULL);
//线程2
handle[1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,NULL,0,NULL);
WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);
}
//第二个按钮:“恢复线程1”
void CDxcTestDmDlg::OnButton2() 
{
ResumeThread(handle[0]);
}

#7


void CDxcTestDmDlg::OnButton1() 
{
    //线程1
    handle[0]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc1,NULL,0,NULL);
    //线程2
    handle[1]=(HANDLE)_beginthreadex(NULL,0,ThreadFunc2,NULL,0,NULL);
    WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);
}
这里的Wait函数在死等,界面线程已经停止响应了。你点不了Button2正常。

#8


WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE);这个第三个参数改成FALSE。
这样Thread2退出,你的界面就能响应了。

#9


To ydfivy:
太对了,感谢!

不过我又有了一个新的问题。如果把线程函数2中的break注释掉,也就是说发现有字母a时(满足条件时),只是挂起线程1,但线程2仍继续循环检测(因为我可以把记事本B中的a手动删除掉),那么这样的话,线程2就永远退不出来,这样即使WaitForMultipleObjects(THREAD_NUM,handle,TRUE,INFINITE)的第三个参数改成FALSE夜不好使了,那该怎么办呢??

//第二个线程:每隔五秒,检测记事本B中是否出现了字母a,若出现了字母a,发出声音,并挂起线程1
unsigned int _stdcall ThreadFunc2(void *pm2)
{
    VARIANT intXR,intYR,width,height;
    dm2.SetPath("I:\\路径");
    //绑定窗口
    dm2.BindWindow(0x59063e,"gdi","windows","windows",0);
    dm2.GetClientSize(0x59063e,&width,&height);
    while(true)
    {
        Sleep(5000);
        long   find_rwret=dm2.FindPic(0,0,width.lVal,height.lVal,"a.bmp","020202",1,0,&intXR,&intYR);
        if(find_rwret>=0)
        {
            dm2.Play("allsuccess.wav");
            ::SuspendThread(handle[0]);
//把break注释掉,也就是说发现有字母a时(满足条件时),只是挂起线程1,但线程2仍继续循环检测(因为我可以把记事本B中的a手动删除掉)
            //break;
        }
    }
    dm2.UnBindWindow();
    return 0;
}

#10


啊O,好复杂。
呵呵。
办法就是把现在做的这些再移动一个工作线程里。然后根据上边那两个线程的状态,设置按钮是disable还是enable.