请教 Delphi 多线程切换输入法后程序假死了

hnsfxtx 2013-05-28 09:34:10
最近遇到程序开启线程后,在主界面编辑框中切换输入法,程序就卡住,只有强制关闭了
线程里只有一个ADODataSet和一个ADOCommand,创建后从设备取数据存入数据库中。
以前类似的线程运行都没问题,现在问题出现后重装输入法,换电脑没能解决。
网上说因为线程中创建了窗口,消息死锁了,但在接收设备数据的时候,没有数据是等待状态 ,循环也处于等待中,执行不了消息解除死锁的过程。
不明白的是类似线程用过不少次了,为什么同样的环境 ,同样的方式 ,现在就出现了这情况了呢?
请高手指点指点!
...全文
297 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yunsuifeng2009 2013-05-31
  • 打赏
  • 举报
回复
果断收藏,以后会用到。
hnsfxtx 2013-05-29
  • 打赏
  • 举报
回复
谢谢大家的关心,问题还是自己解决了。 想太复杂了。 手动消息处理只有在循环可以继续的情况下使用没问题 但我用的线程处理的是硬件数据接收,一直处于等待消息状态,直到有数据上来才会继续,所以在等待的时候作不了其他操作,运行不了那个函数。 公布下解决办法 : 线程中重载Create函数 constructor Create(); 函数中间定义ADODataSet的创建或者创建窗口都行 begin inherited Create(False); //此处创建动态窗体 end; Execute中进行调用操作。 以前都是这样操作的,没出过什么问题,这次图简单,将创建的过程放到了Execute中,才出现了怪现象 ,呵呵。以前也碰到过Execute声明的递增变量偶尔会不按递增规则来,后来线程中只好在上面声明全局变量才放心使用。 欢迎大家帮我解释原理。
lyhoo163 2013-05-29
  • 打赏
  • 举报
回复
线程中要加入消息条件退出语句,这样才不能无限循环(假死)。
武稀松 2013-05-29
  • 打赏
  • 举报
回复
ysai是对的,另外你也可以在线程里面的加上消息循环,这样消息就会跑下去.不会卡在那里了.
zhengcom 2013-05-29
  • 打赏
  • 举报
回复
这仿佛和我的问题一样原因么。 http://bbs.csdn.net/topics/390467455
hnsfxtx 2013-05-28
  • 打赏
  • 举报
回复
线程里操作数据库ADODataSet不影响吧,以前都这样用的
ZyxIp 2013-05-28
  • 打赏
  • 举报
回复
线程里不要操作窗体,如果需要使用消息的方式。
sololie 2013-05-28
  • 打赏
  • 举报
回复
引用 5 楼 ysai 的回复:
这破问题我找了好久原因,楼主赚到了
xhz8000 2013-05-28
  • 打赏
  • 举报
回复
还有这个个说法的!学习了
ysai 2013-05-28
  • 打赏
  • 举报
回复
这破问题我找了好久原因,楼主赚到了
ysai 2013-05-28
  • 打赏
  • 举报
回复
function TCFADODBStorage.OpenConnection: Boolean;

  //线程里打开ADOConnection,在XP下切换输入法程序会死掉
  //原因:ADO自动创建一个ADODB.AsyncEventMessenger窗口,然后会有一个对应的IME窗口,但线程里没有消息循环
  //     XP下输入法切换时会SendMessage给IME窗口并等待返回,IME窗口并不会处理消息,造成死锁
  //这个函数把线程里的IME窗口释放掉,切换输入法时就不会有消息过来了
  procedure _FreeIMEWindow;
  const
    IME_WINDOW_CLASS = 'IME';
    IME_WINDOW_TEXT  = 'Default IME';
  var
    h : HWND;
    pid : DWORD;
    dh : HWND;
  begin
    h :=  FindWindow(IME_WINDOW_CLASS, IME_WINDOW_TEXT);
    while IsWindow(h) do
    begin
      if GetWindowThreadProcessId(h, pid) = GetCurrentThreadId then
        dh  :=  h
      else
        dh  :=  0;
      h :=  FindWindowEx(0, h, IME_WINDOW_CLASS, IME_WINDOW_TEXT);
      if dh <> 0 then
        DestroyWindow(dh);
    end;
  end;

begin
  try
    FConnection.ConnectionString  :=  ConnectionString;
    FConnection.Connected :=  True;
    if GetCurrentThreadId <> Global.MainThreadID{全局的主线程ID,如果是主线程,不需要Free} then
      _FreeIMEWindow;
  except on E: Exception do
    FLastErrorMessage :=  e.Message;
  end;
  Result  :=  FConnection.Connected;
end;
ZyxIp 2013-05-28
  • 打赏
  • 举报
回复
得看你代码具体怎么写的。

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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