我有一个带有这些代码的服务器:
procedure TFrmMain.TCPServerExecute(AContext: TIdContext);
begin
Res := DoRegister(Name,Family,Username,Password);
end;
function TFrmMain.DoRegister(Name,Family,Username,Password:string): bool;
var
Qry: TSQLQuery;
begin
Qry := TSQLQuery.Create(nil);
try
Qry.SQLConnection := FrmConnect.SQLConnection;
Qry.SQL.Text :='INSERT INTO `table` ...';
Qry.ExecSQL();
finally
Qry.Free;
end;
Result := True;
end;
在多个线程中访问一张表是否有问题?以及在 Onexecute 事件中使用什么是危险的?
谢谢 friend 的回复。
那么,为不同的线程建立不同的连接是正确的方法吗?
var
Qry: TSQLQuery;
SqlCon: TSQLConnection;
Begin
SqlCon := TSQLConnection.Create(nil);
Qry := TSQLQuery.Create(nil);
try
SqlCon := FrmConnect.SQLConnection;
Qry.SQLConnection := SqlCon;
finally
SqlCon.Free;
Qry.Free;
end;
end;
最佳答案
您的第二个代码片段不正确。当您应该复制连接字符串时,您正在用全局连接覆盖新连接。您还将释放该全局变量,这可能会给您的应用程序的其余部分带来问题。像这样,取决于你的 TSQLConnection 类的细节:
SqlCon := TSQLConnection.Create(nil); // create
Qry := TSQLQuery.Create(nil);
try
//SqlCon := FrmConnect.SQLConnection; // overwrite!!!
SqlCon.ConnectionString := FrmConnect.SQLConnection.ConnectionString;
SqlCon.Active := true;
Qry.SQLConnection := SqlCon;
...
如果你想拥有一个数据库连接池,那是相当棘手的,因为连接通常是特定于线程的——你需要每个线程一个,你不能在线程之间传递它们。因此,您最终需要编写大量代码来支持它。
我现在使用 OmniThreadLibrary并有一个返回新数据库连接的工厂方法。这为我提供了一个线程池,我将任务输入其中,因此我的特定任务在执行时绑定(bind)到现有线程,但该线程的生命周期相当长。我必须为此编写的代码非常小(我使用的是 ADO):
type
// a factory to generate new instances of our thread-specific data
IThreadPoolData = interface
['{14917B01-6613-4737-B87E-0046789D4284}']
function GetConnection: TADOConnection;
function GetStoredProc: TADOStoredProc;
end;
TThreadPoolData = class(TInterfacedObject, IThreadPoolData)
strict private
FADOConnection: TADOConnection;
FStoredProc: TADOStoredProc; // lazy creation!
public
constructor Create(aConnectionString: string); overload;
destructor Destroy; override;
function GetConnection: TADOConnection;
function GetStoredProc: TADOStoredProc;
end;
// create the connection here so thread creation is slow but using it
// is (relatively) fast
constructor TThreadPoolData.Create(aConnectionString: string);
begin
FADOConnection := TADOConnection.Create(nil);
FADOConnection.LoginPrompt := false;
FADOConnection.ConnectionString := aConnectionString;
FADOConnection.ConnectOptions := coAsyncConnect;
FADOConnection.Connected := true;
end;
destructor TThreadPoolData.Destroy;
begin
FADOConnection.Connected := false;
if assigned(FStoredProc) then
FreeAndNil(FStoredProc);
FreeAndNil(FADOConnection);
end;
如果您编写自己的线程或连接池,则需要做类似的事情。
关于multithreading - 在 OnExecute 事件中使用数据库 (Indy),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3537205/