没用过多线程,可能很简单,大家来帮我解决一下。(100分) ( 积分: 100 )

  • 主题发起人 主题发起人 kena
  • 开始时间 开始时间
K

kena

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在已打开的表(A)记录移动的时候用一个线程来打开另外一个表(B)(主从表,但不能用主从表方式打开,因这个B表记录很多,会出现窗口停顿)。要求是如果A表移动很快时,B表可能还来不及打开上一条,A表已经移动了好几条,所以要求B表只打开与A表当前相应的关联的记录,这个线程应怎样来控制呢?最好回答时加上代码,因为我对线程没怎么了解,谢谢。
 
我想在已打开的表(A)记录移动的时候用一个线程来打开另外一个表(B)(主从表,但不能用主从表方式打开,因这个B表记录很多,会出现窗口停顿)。要求是如果A表移动很快时,B表可能还来不及打开上一条,A表已经移动了好几条,所以要求B表只打开与A表当前相应的关联的记录,这个线程应怎样来控制呢?最好回答时加上代码,因为我对线程没怎么了解,谢谢。
 
用事件机制控制同步呗~
CreateEvent 创建事件
SetEvent 设置事件为已传信
ResetEvent 设置事件为未传信
WaitForSingleObject/WaitForMultipleObjects 等待事件触发
CloseHandle 关闭事件
 
islet8,能不能详细点?
 
你的意思是a如果已经移动了5条,而b才完成上一条,这时b就要跳过a的前4条,而直接去打开第5条?
不太理解你的用意。。
 
对对对,就是这样
 
可以在B线程中直接取第A表中的当前记录就可以了吧
 
mr_piao:话却没错,只是怎么控制呢?第一,B显示的一定要与A表当前的记录相匹配;第二,不能出现窗口停顿的现象(即不能在表的事件里做这些事情)。
 
弄个公共变量,线程a在移动每一条记录的时候都更新这个变量的值,线程b在完成上一条以后就来读这个变量,然后继续执行,那就可以达到你要的效果了
记得这个变量在读写的时候得用临界区保护起来
 
islet8:给点代码吧,我对线程不怎么了解,好不好?
 
我觉得这种情况,你可以从B表中多取些记录作缓存,当缓存中没有的时候再到B表中取,得看你是怎么移动了
 
“线程a在移动每一条记录的时候”应该可以用鼠标单击[表A]所在的表格代替吧,所以用一个线程b应该足够了
线程b要实现的目的是在[表B]中找到与[表A]中对应的数据
-------------------------------------------------------------------------------
假设dbgrid1中为[表A]数据,假设dbgrid2中为[表B]数据,把线程b放在dbgrid1的click事件中,每次单击生成新的线程(用来生成对应的数据集)来提高速度。
由于新开线程b来处理dbgrid2中数据,所以停顿也只是体现在dbgrid2中,现在的问题是:1、如何解决线程b和dbgrid1单击事件的同步;2、如何解决线程b的查询速度。
对于第一个问题,由于每次单击都会新生成一个对应的线程,可以达到即时响应,每个线程都会生成对应的数据集,在生成数据集后需要判断该数据集是否为最近一次单击所产生的,这可以通过设置的公共变量来解决,如果是则更新dbgrid2的数据集。注意释放用过的线程和数据集。
对于第二个问题,优化where,另外你可以考虑通过select top n(select top n * i ...where... desc) 来减少返回的记录数来提高速度
 
我已经实现了这个功能,线程类的代码如下:
unit UnitThread;
interface
uses
Classes,ComObj,Activex,ADODB,UnitPub,Messages,Windows,Sysutils,UnitData;
type
tMyThread = class(TThread)
private
{ Private declarations }
fKey:string;
protected
procedure Execute;
override;
procedure PutData;
public
ADOConn:TADOConnection;
ADQ:TADOQUery;
end;

implementation
{ Important: Methods and properties of objects in VCL or CLX can only be used
in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure tMyThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{ tMyThread }

procedure tMyThread.Execute;
var
aMsg:TagMsg;
akey,bkey:string;
begin
OleInitialize(nil);
ADOConn := TADOConnection.Create(nil);
ADOConn.LoginPrompt := False;
ADOConn.ConnectionString := 'Provider=SQLOLEDB.1;Password=4rt5e6;Persist Security Info=True;User ID=sa;Initial Catalog=indexdb;Data Source=192.168.10.237';
ADQ := TADOQuery.Create(nil);
ADQ.Connection := ADOConn;
while GetMessage(aMsg,0,0,0)do
begin
if Terminated then
Break;
if aMsg.message = WM_MYMessage then
begin
WaitForSingleObject(hMutex,INFINITE);
aKey := key;
ReleaseMutex(hMutex);
if (aKey = '') or (aKey = fKey) then
Continue;
fkey := akey;
ADQ.Close;
ADQ.SQL.Text := 'select * from wfyw where qcode = ' + QuotedStr(akey);
ADQ.Open;
Sleep(300);
WaitForSingleObject(hMutex,INFINITE);
bKey := key;
if akey = bkey then
begin
Synchronize(PutData);
end;
ReleaseMutex(hMutex);
end;

end;
ADOConn.Free;
ADQ.Free;
OleUninitialize;
end;

procedure tMyThread.PutData;
begin
if not MyData.YWQR.ControlsDisabled then
mydata.YWQR.DisableControls;
MyData.YWQR.Close;
MyData.YWQR.Clone(ADQ);
if MyData.YWQR.ControlsDisabled then
Mydata.YWQR.EnableControls;
end;

end.
 
然后在主表的 AfterScroll事件中:
WaitForSingleObject(hMutex,INFINITE);
key := DataSet.fieldbyname('qcode').AsString;
ReleaseMutex(hMutex);
PostThreadMessage(Self.ThreadID,WM_MYMessage,0,0);
在主Form Unit中:
MyData.LWQR.Close;
MyData.LWQR.SQL.Text := 'select * from wflw where qcode like ''X039199%''';
MyData.LWQR.Open;
aThread := tMyThread.Create(True);
MyData.ThreadID := aThread.ThreadID;
athread.Resume;
 
后退
顶部