关于MFC调用线程的问题,在线等答案!

node2017 2012-08-12 04:10:08
最近用MFC写一个语音的程序,调用了微软的speech。
想法是想程序一直处于监听状态,所以在对话框处理函数中写了一个while循环。但是这个方法会导致while循环在主线程导致程序假死。(能运行,也能用,就是在运行时点击对话框的其他部分会造成“未响应”)
于是就想用多线程来调用这个函数,开启了一条线程。这个时候,问题又来了,把循环放在线程中,又不能正确地执行create()函数,导致内存出错。

调用的类是这样的:
class LANE_SPEECH_DLL CSR
{
public:
void GetRecoWordA ( char * pchRecoWord );
bool StartReco();
CSR();
bool Create( const DWORD dwLanguage = SP_CHINESE,
const bool bInproc = true );
bool LoadCrammarFile ( const WCHAR * pwchFilename );
void ProcessReco( const DWORD dwMilliseconds = 5000 ); //处理识别事件
bool IsRecoSuccess() const; //识别成功则返回true
bool IsRecoEnd() const; //识别结束则返回true
virtual ~CSR();


protected:
CComPtr<ISpRecognizer> m_pSREngine; // 语音识别引擎(recognition)的接口。
CComPtr<ISpRecoContext> m_pSRContext; // 识别引擎上下文(context)的接口。
CComPtr<ISpRecoGrammar> m_pSRGrammar; // 识别文法(grammar)的接口。
CComPtr<ISpStream> m_pInputStream; // 流()的接口。
CComPtr<ISpObjectToken> m_pToken; // 语音特征的(token)接口。
CComPtr<ISpAudio> m_pAudio; // 音频(Audio)的接口。(用来保存原来默认的输入流)
};


主窗口中的线程代码:

UINT CTestDlg::start(LPVOID lpParam)
{
CTestDlg * a=(CTestDlg *)lpParam;
a->SetDlgItemText(IDC_1,_T("关闭线程"));
//语音部分

CString s;
CSR sr;
while(a->run)
{


sr.Create(); //这个函数不能正确调用,返回值是false,这里出现问题
sr.LoadCrammarFile( L"grammar.xml" );
sr.StartReco();
sr.ProcessReco(1500);
if ( sr.IsRecoEnd() && sr.IsRecoSuccess() )
{
char temp[128];
sr.GetRecoWordA( temp );
s = temp;
if ( s == "启动")
{
a->m_edit=s;
a->UpdateData(FALSE);
AfxMessageBox ( "小车即将启动" );
}
else if ( s == "下一页" )
{
a->m_edit=s;
a->UpdateData(FALSE);
AfxMessageBox ( "小车即将停止" );

}
else if ( s == "左转" )
{
AfxMessageBox ( "小车即将左转" );
}
else if ( s == "右转" )
{
AfxMessageBox ( "小车即将右转" );
}
else if ( s == "加速" )
{
AfxMessageBox ( "小车即将加速" );
}
else if ( s == "减速" )
{
AfxMessageBox ( "小车即将减速" );
}
else if ( s == "退出程序" )
{
AfxMessageBox ( "程序即将退出" );
a->run=FALSE;
//PostQuitMessage(0);
}*/
sr.~CSR();



}
a->SetDlgItemText(IDC_1,_T("开启线程"));
a->run=FALSE;
return 0;
}

各位大神,请问有什么办法可以在线程中调用这个类的create函数。是不是因为这个类是dll所以不能放在线程中还是什么错了?
还是有什么其他办法可以做到我想的效果
...全文
274 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Space丶Miao 2015-04-22
  • 打赏
  • 举报
回复
楼主,你好,我从网上下载了类似的代码,但是调试的时候总是这个错误: 错误error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: bool __thiscall CSR::LoadCrammarFile(wchar_t const *)" (__imp_?LoadCrammarFile@CSR@@QAE_NPB_W@Z),该符号在函数 "protected: virtual int __thiscall CTestDlg::OnInitDialog(void)" (?OnInitDialog@CTestDlg@@MAEHXZ) 中被引用 我知道是连接库的问题,既然楼主的可以调试成功能告诉我这个解决方案需要 连接什么库么?
xdd10jishi 2012-08-14
  • 打赏
  • 举报
回复
><继续坐等答案呢!!!
xdd10jishi 2012-08-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
你说的问题太模糊了, 你是说想在子线程中操作主线程传入的一人对象吧, 有些跨线程操作是会引起失败的,Winsocket就是个例子

1.建议子线程给主线程发消息的方式,在主线程中触发完成你想要的操作
2.操作主线程控件可能通过主线程的指针(在子线程中定义一个指向主线程的指针,启动子线程的时候,把主线程指针赋给它),也可直接通过传参数的方式把主线程指针通到子线程,同时也可通过给主线程发消息的方……
[/Quote]

因为我那个操作想要一直循环的,但是放在主线程中失去焦点(鼠标点击到其他地方)就会出现未响应。所以就像用子线程来做循环,这样不会造成程序假死。
想你说的方法,会不会也是造成程序假死的状况呢???
suiyuan1767 2012-08-14
  • 打赏
  • 举报
回复
你可以自定义消息,进行子线程与主线程的通信。子线程响主线程发消息,在主线程中响应进行你要的操作,不需要你说的鼠标焦点
MingoJ 2012-08-13
  • 打赏
  • 举报
回复
你说的问题太模糊了, 你是说想在子线程中操作主线程传入的一人对象吧, 有些跨线程操作是会引起失败的,Winsocket就是个例子

1.建议子线程给主线程发消息的方式,在主线程中触发完成你想要的操作
2.操作主线程控件可能通过主线程的指针(在子线程中定义一个指向主线程的指针,启动子线程的时候,把主线程指针赋给它),也可直接通过传参数的方式把主线程指针通到子线程,同时也可通过给主线程发消息的方式,能过消息触发主线程完成相应的操作
xdd10jishi 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
线程函数中不要直接操作控件,改用发送消息到UI线程,在自定义消息响应函数中去更新控件信息。
[/Quote]

我试过把原本放在线程的操作放在一个函数中,线程去调用它也是不成功。但是把操作放在一个按钮中去响应就可以。会不会这个操作只能放在主线程中呢?????
xdd10jishi 2012-08-13
  • 打赏
  • 举报
回复
继续等答案啊,各位大神帮帮我们吧~~~
xdd10jishi 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]
线程函数中不要直接操作控件,改用发送消息到UI线程,在自定义消息响应函数中去更新控件信息。
[/Quote]

这个是我不能成功调用create()函数的原因吗??怎样才算直接操作控件呢!!?^-^
Eleven 2012-08-13
  • 打赏
  • 举报
回复
线程函数中不要直接操作控件,改用发送消息到UI线程,在自定义消息响应函数中去更新控件信息。
Gloveing 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 的回复:]

引用 1 楼 的回复:
在线程外定义变量,用参数传进线程里试试。


不行哎~~~我调用的那个函数的类型是不是不能放在线程里的?
[/Quote]
不是,你还是贴一下创建线程,传参的代码部分吧
xdd10jishi 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
引用 7 楼 的回复:

引用 1 楼 的回复:
在线程外定义变量,用参数传进线程里试试。


不行哎~~~我调用的那个函数的类型是不是不能放在线程里的?

不是,你还是贴一下创建线程,传参的代码部分吧
[/Quote]



UINT CTestDlg::start(LPVOID lpParam)
{
// CTestDlg * a=(CTestDlg *)lpParam;
CSR * sr=(CSR *)lpParam;

// a->SetDlgItemText(IDC_1,_T("关闭线程"));
//语音部分

CString s;

while(1)
{


//sr->Create();
sr->LoadCrammarFile( L"grammar.xml" );
sr->StartReco();
sr->ProcessReco(1500);
if ( sr->IsRecoEnd() && sr->IsRecoSuccess() )
{
char temp[128];
sr->GetRecoWordA( temp );
s = temp;
if ( s == "启动")
{
// a->m_edit=s;
// a->UpdateData(FALSE);
AfxMessageBox ( "小车即将启动" );
}
else if ( s == "下一页" )
{
// a->m_edit=s;
// a->UpdateData(FALSE);
AfxMessageBox ( "小车即将停止" );

}
...
}


void CTestDlg::On1()
{
// TODO: Add your control notification handler code here
if(run)
{
run=FALSE;
}
else
{
run=TRUE;
CSR k;
k.Create();
//k.LoadCrammarFile( L"grammar.xml" );

AfxBeginThread(start,&k);
}
}
xdd10jishi 2012-08-12
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
在线程外定义变量,用参数传进线程里试试。
[/Quote]

不行哎~~~我调用的那个函数的类型是不是不能放在线程里的?
xdd10jishi 2012-08-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 heksn 的回复:]
在线程外边Create
[/Quote]

我也试过在线程外面create也不行,轮到sr.LoadCrammarFile( L"grammar.xml" );
这个函数出现问题了运行的时候。。。
xdd10jishi 2012-08-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // t……
[/Quote]

我就是那样传进去,还是同样的问题,create函数出错了。
  • 打赏
  • 举报
回复
在线程外边Create
Gloveing 2012-08-12
  • 打赏
  • 举报
回复
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier);
通过参数lpParameter传参进去
node2017 2012-08-12
  • 打赏
  • 举报
回复
你的意思是把变量作为线程的参数吗?
刚刚试过也是不行啊
gold_water 2012-08-12
  • 打赏
  • 举报
回复
在线程外定义变量,用参数传进线程里试试。

679

社区成员

发帖
与我相关
我的任务
社区描述
智能路由器通常具有独立的操作系统,包括OpenWRT、eCos、VxWorks等,可以由用户自行安装各种应用,实现网络和设备的智能化管理。
linuxpython 技术论坛(原bbs)
社区管理员
  • 智能路由器社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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