增加了一个线程,在程序运行的时候切换输入法,程序就死了。。。(200分)

  • 主题发起人 萧西风
  • 开始时间

萧西风

Unregistered / Unconfirmed
GUEST, unregistred user!
RT
。请高手们帮忙啊。。。。。。SOS
 
这个是有问题的 在输入发切换会影响的 这个现在也没有好方法 是输入法问题,不过可以线称不要设置堵塞模式可以解决 以前也遇到过这样的问题
 
来自:delphfans, 时间:2008-7-24 14:14:13, ID:3909944
这个是有问题的 在输入发切换会影响的 这个现在也没有好方法 是输入法问题,不过可以线称不要设置堵塞模式可以解决 以前也遇到过这样的问题
具体是??设置堵塞模式
 
unit UpdateDataThread;
interface
uses
Sysutils, Forms, Controls, Windows, classes,StrUtils,FileCtrl,IniFiles,ExtCtrls,ShellAPI,DB,
ADODB, ComObj,Activex,Messages, ComCtrls, DBTables, Syncobjs;
type
TWorker=class
private
datas:TStringList;
Event:TSimpleEvent;
Lock:TCriticalSection;
public
procedure add(sql:String);
function get:String;
function wait(timeout:DWORD):TWaitResult;
Constructor Create;
Destructor Destroy;override;
end;

TUpdateThread = class(TThread)
private
connectionString:String;
Worker:TWorker;
procedure Runs(query:TADOQuery);
protected
procedure Execute;
override;
public
Constructor Create(connectionString:String;
Worker:TWorker);
end;

var
QUeryThread: TUpdateThread;
implementation
{ UpdateThread }
//功能:线程类的构造器
constructor TUpdateThread.create(connectionString:String;
Worker:TWorker);
begin
inherited Create(true);
self.connectionString:=connectionString;
self.Worker:=Worker;
FreeOnTerminate := True;
Resume;
end;

//功能:执行线程的方法
//说明:每个线程创建单独的数据连接
procedure TUpdateThread.Execute;
var
aUpdateQry :TADOQuery;
MyConnet:TADOConnection;
abegin
Id,aCheckComId:integer;
aIndexbegin
:integer;
aGetComStr:string;
begin
//使用com对象必须要初始化
CoInitialize(nil);

try
MyConnet:= TADOConnection.Create(nil);
aUpdateQry:=TADOQuery.Create(nil);
try
aUpdateQry.Connection:=MyConnet;
MyConnet.ConnectionString :='Provider=Microsoft.Jet.OLEDB.4.0;Password="";User ID=Admin;Data Source='+self.connectionString;
MyConnet.LoginPrompt :=false;
MyConnet.Open;
except
exit;
end;
while not Terminateddo
begin
self.Runs(aUpdateQry);
sleep(10);
end;

finally
aUpdateQry.Free;
MyConnet.Free;
CoUninitialize;
//必须使用
end;

end;

procedure TUpdateThread.Runs(query:TADOQuery);
var
aSetStr:string;
begin
self.Worker.wait(INFINITE);
aSetStr:=self.Worker.get;
if aSetStr<>'' then
begin
with querydo
begin
Close;
SQL.Clear;
SQL.Add(aSetStr);
try
ExecSQL;
except
end;
end;
end;

end;

{ TWorker }
procedure TWorker.add(sql: String);
begin
Lock.Acquire;
try
datas.Add(sql);
Event.SetEvent;
finally
Lock.Release;
end;
end;

constructor TWorker.Create;
begin
datas:=TStringList.Create;
Event:=TSimpleEvent.Create;
Lock:=TCriticalSection.Create;
end;

destructor TWorker.Destroy;
begin
Lock.Free;
Event.Free;
datas.Free;
inherited;
end;

function TWorker.get: String;
begin
Lock.Acquire;
try
Result:='';
if datas.Count>0 then
begin
result:=datas.Strings[0];
datas.Delete(0);
end
else
begin
Event.ResetEvent;
end;
finally
Lock.Release;
end;
end;

function TWorker.wait(timeout: DWORD):TWaitResult;
begin
Result:=Event.WaitFor(timeout);
end;

end.
 
高手们出来指点下阿!
 
//据说在下面加
while not Terminateddo
begin
self.Runs(aUpdateQry);
Application.ProcessMessages;
//就加一句,但我不保证不会出其他问题啊
sleep(10);
end;
 
在其他机子运行也是这样吗?
 
来自:ch2001023, 时间:2008-7-24 18:40:14, ID:3910022
在其他机子运行也是这样吗?

是的,都一样!
可是我看了demo,没有出现切换输入法就出问题的阿。。。郁闷阿,难道我的程序写错了??
 
来自:kk2000, 时间:2008-7-24 18:22:16, ID:3910018
//据说在下面加
while not Terminateddo
begin
self.Runs(aUpdateQry);
Application.ProcessMessages;
//就加一句,但我不保证不会出其他问题啊
sleep(10);
end;

不行,解决不了!
 
可能不是线程的问题,因为线程相当于让权,意味着同步执行...造成程序假死,说明有任务让其他等待的时间太长导致的...再仔细看看程序里面有没有耗时的操作,再用 Application.ProcessMessages;让出权
 
Event.SetEvent;
这样最好不用 可以把进程的 hwnd 传 进去执行完 发个消息给外部窗体 用消息 处理
 
我原来也遇到过类似的问题,但是是在Thread中使用ADO,切换输入法时发生冲突,据说是在线程中调用COM对象(比如说ADO),会使COM类库内置窗体拦截其他线程的消息,可以使用CoWaitForMultipleHandles代替Sleep等待信号对象。我实际的解决方法使在线程中建立一个消息循环,后来就没有问题,仅供参考!
 
来自:delphfans, 时间:2008-7-29 12:11:33, ID:3910792
Event.SetEvent;
这样最好不用 可以把进程的 hwnd 传 进去执行完 发个消息给外部窗体 用消息 处理

具体请赐教!!
 
来自:一只没有缺点的狼, 时间:2008-7-29 20:35:59, ID:3910894
我原来也遇到过类似的问题,但是是在Thread中使用ADO,切换输入法时发生冲突,据说是在线程中调用COM对象(比如说ADO),会使COM类库内置窗体拦截其他线程的消息,可以使用CoWaitForMultipleHandles代替Sleep等待信号对象。我实际的解决方法使在线程中建立一个消息循环,后来就没有问题,仅供参考!

请赐教!!
 
procedure TDataPool.Execute;
var
m_TMsg:TMsg;
//消息句柄
m_TGetTask:THandle;
//关闭事件
m_BRunning:boolean;
//指示线程是否处于运行
begin
{ Place thread code here }
//指示ADO的服务器建立支持多线程并发访问的环境
//CoInitializeEx(nil,COINIT_MULTITHREADED);
try
//初始化数据库连接
AQ:=nil;
if InitADO() then
begin
//建立线程的消息循环
PeekMessage(m_TMsg,0,WM_USER,WM_USER,PM_NOREMOVE);
m_TGetTask:=FManager.ExecTask;
m_BRunning:=True;
while (not Terminated) and (not FManager.GoOut) and m_BRunningdo
begin
case MsgWaitForMultipleObjects(1, m_TGetTask, False, INFINITE, QS_ALLINPUT) of
WAIT_OBJECT_0:
begin
m_BRunning:=False;
end;
WAIT_OBJECT_0+1:
begin
while PeekMessage(m_TMsg,0,0,0,PM_REMOVE)do
begin
if m_TMsg.hwnd = 0 then
begin
case m_TMsg.message of
WM_EXECTASK:
begin
//处理消息
end;
WM_SHUTDOWNPOOL:
begin
//处理消息
end;
else
begin
//分发消息
DispatchMessage(m_TMsg);
end;
end;
end else
begin
//分发消息
DispatchMessage(m_TMsg);
end;
end;
end;
end;
end;
end else
begin
//ADO初始化失败处理
end;
finally
//断开清除数据库连接
FreeADO();
//清除ADO环境
CoUninitialize();
end;
end;
这样建立一个消息循环,初始化ADO环境的时候,多加一个参数
 
多线程程序切换输入法导致死机的问题及解决方案
http://blog.csdn.net/hero_yin/archive/2008/08/06/2777425.aspx
希望能帮你
 
做个记号,收藏之
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
926
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
顶部