I need some help, i'm coding a dll who modify some value from a app. but if i freeze the value app crashs (Stop Working after some time).
This is my code:
Here i create a thread who updates the address:
CreateThread(nil, 0, #UpdateAddr, Pointer(nil), 0, rodaid)
and here is the function UpdateAddr:
procedure UpdateAddr;
var
BytesWrite: DWORD;
buf: Cardinal;
begin
while true do
begin
buf := Random(38);
WriteProcessMemory(ProcessH, SpeedAddr, addr(buf), sizeof(buf), BytesWrite);
end;
end;
And here how i open the process:
ProcessH := OpenProcess (PROCESS_ALL_ACCESS, False, ProcessId);
For any reason who i dont know the app crashs after some time when the thread are created.
Somebody can help me?
A few problems that I can see. Including:
No error checking.
Requesting PROCESS_ALL_ACCESS which is more than you need.
The thread procedure has the wrong signature.
The last one of these would explain a crash in your app, but not the other app. The thread procedure should be:
function ThreadProc(lpParameter: Pointer): DWORD; stdcall;
Most likely the other app is crashing because you are screwing with its memory. Try removing the call to WriteProcessMemory and see if the other app stops crashing.
Related
I am new with this stuff of Threading in Delphi. so, I am trying to make a simple query aplication that make a bit call up for the database and take a bit of time, so I want to alert the user that there is a background process and have to be patient.
I tried many samples, but none of them work for me, Please, could somebody show me a simple sample that could work?
I know that I have to Declare a Type of TThread, with Create and Override Execute... etc.. but since that I am lost...
Using Delphi 7, SQL Server 2005 and ADO, Windows XP sp3.-
Thanks.
Yup, you declare a new type which inherits from TThread:
TMyWorkerThread = class(TThread)
end;
Then you add a function override for Execute():
TMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
That procedure will be called when you start your thread. It will be executed in parallel with your main program. Let's write it.
procedure TMyWorkerThread.Execute;
begin
//Here we do work
DoSomeWork();
DoMoreWork();
//When we exit the procedure, the thread ends.
//So we don't exit until we're done.
end;
How to use this? Let's say you want to start doing work when the user clicks button. You write an OnClick handler:
procedure TMainForm.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
That's it. After the user clicks button, your thread starts and proceeds with doing whatever it is that you wrote in Execute. If the user clicks the button again, another thread will start, and then another - one every click. They will all run in parallel, each doing all what's written in Execute() and then ending.
Let's say you want to check if the work is over. For that, you'll have to store the reference to your thread somewhere:
TMainForm = class(TForm)
{...skipped...}
public
MyWorkerThread: TThread;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
//This time we make sure only one thread can be started.
//If one thread have been started already, we don't start another.
if MyWorkerThread<>nil then
raise Exception.Create('One thread have already been started!');
MyWorkerThread := TMyWorkerThread.Create(false);
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
//If the work is not over yet, we display message informing the user we're still working
if (MyWorkerThread<>nil) and (WaitForSingleObject(MyWorkerThread.Handle, 0)<>WAIT_OBJECT_0) then
MessageBox(Self.Handle, pchar("The work is not yet done!"), pchar("Still running"), MB_OK);
end;
As you see, we're checking if a thread is still running by calling a Windows function called WaitForSingleObject. This function waits until the thread is done working, or the timeout is elapsed, and as we specify the timeout of 0, it just exists immediately if the thread is not over yet.
You can find many examples on the web of threads. The only special feature, if you are using ADO connections inside the Thread, is that you can't share the same connection.
Each thread must create its own connection, otherwise they are equal (should follow the same rules as any other thread.)
An sample that I have used is this:
TADOSQLThread = class(TThread)
private
FADOQ: TADOQuery; // Internal query
FSQL: string; // SQL To execute
FID: integer; // Internal ID
public
constructor Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
destructor Destroy; override;
procedure Execute(); override;
property ID:integer read FID write FID;
property SQL:string read FSQL write FSQL;
property ADOQ:TADOQuery read FADOQ write FADOQ;
end;
The Create constructor is overrided, and look like this:
constructor TADOSQLThread.Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
begin
inherited Create(CreateSuspended);
// ini
Self.FreeOnTerminate := False;
// Create the Query
FADOQ := TAdoquery.Create(nil);
// assign connections
FADOQ.ConnectionString := AConnString;
FADOQ.SQL.Add(ASQL);
Self.FID := IDThread;
Self.FSQL:= ASQL;
end;
And the execute method is very simple:
procedure TADOSQLThread.Execute();
begin
inherited;
try
// Ejecutar la consulta
Self.FADOQ.Open;
except
// Error al ejecutar
...Error treattement
end;
end;
To start and create a thread you can use code similar to this:
//crear el Thread
th := TADOSQLThread.Create(True, mmConnection.Lines.Text, ASQL, AId);
// internal for me (for controled the number of active threads and limete it)
inc(numThreads);
// evento finalizacion
th.OnTerminate := TerminateThread;
// Ejecutarlo
th.Resume;
I have create a TerminateThread method that receive the control of threads when they finish. The only different to other threads is the connection problem. You must create a new connection on every thread, It can't share the same ADOConnections with others.
I hope this example will be useful for you.
Regards
I'm fairly new to IPC(interprocess communication). Doing my research, I decided on the Named pipes.
My application consists of 2 parts: a monitoring app, and a UI dashboard. The dashboard receives updates from the monitor constantly and shows stats, the user should be able to change certain parameters of the monitor through the dashboard (refresh rate, restart process,scheduled task...) so it has to be a bidirectional communication. The Monitor would later become a service application, but that's a plan for later.
Getting to the point, I used the Pipes unit by Overbyte(Francois Piette) v1.01
and followed the example made on their website. When connecting the pipes on the main thread, it functions normally. But due to my monitor needing a separate thread to (monitor-send message-sleep-loop...), when I try to connect on the other thread, I get an error "The notify window and the component window do not exist in the same thread!"
What I need to know is, can named pipes communicate using a separate thread? (Judging by the error msg, I feel it may be fetching the window handle on the main UI and would not work on a different thread)
Is there a better way to implement my application? or named pipes better than Overbyte?
Sample of my code:
TThreadMonitor = Class(TThread)
private
PipeClient1: TPipeClient;
listOfProcesses: Array of String;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
procedure ConnectPipe;
procedure SendMessage(const Msg: String);
End;
var
t: TThreadMonitor;
procedure TClientFormMain.BtnDifferentThreadClick(Sender: TObject);
begin
t := TThreadMonitor.Create(TRUE);
t.FreeOnTerminate := TRUE;
t.Start;
end;
procedure TThreadMonitor.ConnectPipe;
begin
if not PipeClient1.Connect(2000, TRUE) then
LogThis('Pipe connection failed', LogFilePath, TRUE)
else
LogThis('Pipe connected', LogFilePath, TRUE);
end;
procedure TThreadMonitor.Execute;
begin
inherited;
ConnectPipe; //<---throws exception here although getting "Pipe Connected"
while not Terminated do
begin
for i := 0 to Length(listOfProcesses) - 1 do
begin
...
MonitorProcess(listOfProcesses[i]);
...
end;
sleep(2000);
end;
end;
When my main application (Delphi 2009) terminates, I want it to signal my threads (timers, TDataModules with ADO Connections, SMTP etc) to dispose gracefully.
In my main application, I have the following:
try
PostThreadMessage(bpvccMAILER.ThreadID, WM_SYSTEM_CLOSE, self.Handle, 0);
returnMessage := (SysErrorMessage(GetLastError)); //Returns 'The operation completed successfully'
while TRUE do
begin
sleep(1000);
if not (Assigned(bpvccMAILER)) then
begin
bpvccACTIVITY_LOGGER.Write('SHUTDOWN','TBPVCommunicatorGUI.FormClose - All Threads have shut down');
break;
end;
locWaited := locWaited + 10;
end;
except
end;
finally
FreeAndNil(bpvccACTIVITY_LOGGER);
FreeAndNil(bpvccMAILER);
end;
Thread class:
TBPVMailer = class(TThread)
protected
SMTP : TIdSMTP;
interval : Integer;
fMain : Integer;
fMainIsSvc : Boolean;
fTerminated: Boolean;
function SendEmail(AEmail: TEmailObj) : TBPVEmailSendResult;
function doSleep : Boolean;
procedure Write(AStatus, AMessage : String);
procedure FlushQueue();
procedure HandleMessage(var Message : TMessage); message WM_SYSTEM_CLOSE;
public
constructor Create(AServer : String; APort : Integer; AUser, APass : String; AInterval : Integer; StartSuspended : Boolean); overload;
procedure Execute; override;
procedure QueueEmail(AEmail: TEmailObj; EmailType : TBPVEmailType; AssociatedID : String);
destructor Destroy; override;
end;
procedure TBPVMailer.HandleMessage(var Message: TMessage);
var
msg : tagMSG;
begin
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
fMain := Message.WParam;
fMainIsSvc := Message.LParam = 1;
fTerminated := TRUE;
end;
Problem is, Assigned(bpvccMAILER) always returns true even after calling PostThreadMessage. Also, bpvccMAILER.fTerminated is always FALSE, which means the TBPVMailer.HandleMessage is never executed because that is were the value is set to TRUE. What am I doing wrong, it appears that my threads arent receiving the messages?
The obvious explanation is that you don't have a message pump in your thread. You post the message, but the thread does not pump its queue.
The code is needlessly complex though. There seems to be no need for messages at all. Call the Terminate method of the thread and then use its WaitFor method to wait until it stops. Or even simpler, just call Free on the thread.
Your code does contain a number of oddities:
Why do you call PeekMessage? That serves no purpose that I can discern.
Waiting with Sleep should be avoided. You can almost always use dedicated wait functions.
It's odd the you wait until bpvccMAILER is nil, but then use FreeAndNil(bpvccMAILER).
You must only call GetLastError when it is well-defined. Typically that is only when the preceeded API call has failed. And failure is indicated by the value returned by the API call.
The Sleep loop in the main thread is not OK since it blocks processing messages.
Just call the PostThreadMessage and return, without any Sleep loop afterwards.
If you need to wait until bpvccMAILER finishes, add code that on completion send a PostMessage to your main thread. So, the main thread will handle this message and will be aware that the auxiliary thread has finished. It may not be easy to change your application this way straight from the start, but little by little you will be designing applications in such a way that always does correct thread handling.
Besides that, if you use PostThreadMessage, then your Thread.Execute loop must have MsgWaitForMultipleObjects.
Here is an example on how the Thread.Execute loop have to be:
<skipped>
repeat
<skipped>
R := MsgWaitForMultipleObjects(EventCount, EventArray, False, INFINITE, QS_ALLINPUT);
<skipped>
if R = WAIT_OBJECT_0 + EventCount then
begin
while PeekMessage(M, 0, 0, 0, PM_REMOVE) do
begin
if M.Message = WM_QUIT then
Break;
TranslateMessage(M);
DispatchMessage(M);
end;
if M.Message = WM_QUIT then
Break;
end;
<skipped>
until Terminated;
<skipped>
If your application will eventually need to exit while the tread is running (assume your thread object is in T variable), do the following:
T.Terminate;
SetEvent([one of the event of the EventArray]); // we should call it AFTER terminate for the Terminated property would already be True when the tread exits from MsgWaitForMultipleObjects
T.WaitFor;
T.Free; // "Free" calls "WaitFor" anyway, but Remy Lebeau suggests to explicitly call "WaitFor" before "Free".
T := nil;
Okay guys, I'm using TClientSocket class and Threads to work simultaneously with a list of hosts. It's all good but I started note that after sometime, all threads get stucked into a ReceiveBuf call... If I open 10 threads, to check 100 hosts for example, it will start good, but after sometime all threads will be stucked because for some reason some hosts don't answer fine for this ReceiveBuf call... I tried to do a ReceiveLength and check if receive > 0, to call the ReceiveBuf, but still not working.
I'll post the original code below:
function Threads.ReceiveProtocolVersion;
var
ProtocolVersion: array[0..11] of AnsiChar;
begin
try
MySocket.Socket.ReceiveBuf(ProtocolVersion, SizeOf(ProtocolVersion));
Version:= AnsiString(ProtocolVersion);
...//continues but doesn't matter because many threads get stucked in the ReceiveBuf call...
except
Terminate; //we terminate thread if raise some exception..
Ok, so after some researchs, I started tryin to do like this:
function Threads.ReceiveProtocolVersion;
var
ProtocolVersion: array[0..11] of AnsiChar;
SizeBuf: integer;
begin
try
SizeBuf:= MySocket.Socket.ReceiveLength;
if SizeBuf > 0 then
begin
MySocket.Socket.ReceiveBuf(ProtocolVersion, SizeOf(ProtocolVersion));
Version:= AnsiString(ProtocolVersion);
....
end;
except
Terminate; //we terminate thread if raise some exception..
Apparently, it solved the problem about threads getting stucked in ReceiveBuf call, but for some unknown reason, none (not even the ones that was working right) threads get inside the 'if SizeBuf > 0'.
Any help?
//Edit showing more of Thread code::
The Thread.Execute is like this:
procedure MyThread.Execute;
begin
while not(Terminated) do
begin
if SocketConnect then
begin
if ReceiveProtocolVersion then
begin
DoAuthentication;
end;
end;
MySocket.Close;
MySocket.Free;
end;
Terminate;
end;
The SocketConnect function is:
function MyThread.SocketConnect: bool;
begin
Result:= false;
MySocket:= TClientSocket.Create(Nil);
MySocket.Port:= StrToInt(Form1.Edit1.Text);
MySocket.ClientType:= ctBlocking;
MySocket.Host:= Host; //Host is a private variable for thread class
try
MySocket.Active:= true;
if (MySocket.Socket.Connected = true) then
Result:= true;
except
Terminate;
end;
end;
I fix the problem using TWinSocketStream. Something like this:
function MyThread.CheckProtocol: bool;
var
SockStream: TWinSocketStream;
ProtocolVersion: array[0..11] of AnsiChar;
begin
try
SockStream := TWinSocketStream.Create(MySocket.Socket, 3000);
SockStream.Read(ProtocolVersion, SizeOf(ProtocolVersion));
RFBVer:= AnsiString(ProtocolVersion);
....
I read that the correct way to work with blocking-mode sockets is by sending/receiving data over TWinSocketStream in:
DocWiki Embarcadero
Anyway, thank for the guys who tried to help!
I am new with this stuff of Threading in Delphi. so, I am trying to make a simple query aplication that make a bit call up for the database and take a bit of time, so I want to alert the user that there is a background process and have to be patient.
I tried many samples, but none of them work for me, Please, could somebody show me a simple sample that could work?
I know that I have to Declare a Type of TThread, with Create and Override Execute... etc.. but since that I am lost...
Using Delphi 7, SQL Server 2005 and ADO, Windows XP sp3.-
Thanks.
Yup, you declare a new type which inherits from TThread:
TMyWorkerThread = class(TThread)
end;
Then you add a function override for Execute():
TMyWorkerThread = class(TThread)
public
procedure Execute; override;
end;
That procedure will be called when you start your thread. It will be executed in parallel with your main program. Let's write it.
procedure TMyWorkerThread.Execute;
begin
//Here we do work
DoSomeWork();
DoMoreWork();
//When we exit the procedure, the thread ends.
//So we don't exit until we're done.
end;
How to use this? Let's say you want to start doing work when the user clicks button. You write an OnClick handler:
procedure TMainForm.Button1Click(Sender: TObject);
begin
TMyWorkerThread.Create(false);
end;
That's it. After the user clicks button, your thread starts and proceeds with doing whatever it is that you wrote in Execute. If the user clicks the button again, another thread will start, and then another - one every click. They will all run in parallel, each doing all what's written in Execute() and then ending.
Let's say you want to check if the work is over. For that, you'll have to store the reference to your thread somewhere:
TMainForm = class(TForm)
{...skipped...}
public
MyWorkerThread: TThread;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
//This time we make sure only one thread can be started.
//If one thread have been started already, we don't start another.
if MyWorkerThread<>nil then
raise Exception.Create('One thread have already been started!');
MyWorkerThread := TMyWorkerThread.Create(false);
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
//If the work is not over yet, we display message informing the user we're still working
if (MyWorkerThread<>nil) and (WaitForSingleObject(MyWorkerThread.Handle, 0)<>WAIT_OBJECT_0) then
MessageBox(Self.Handle, pchar("The work is not yet done!"), pchar("Still running"), MB_OK);
end;
As you see, we're checking if a thread is still running by calling a Windows function called WaitForSingleObject. This function waits until the thread is done working, or the timeout is elapsed, and as we specify the timeout of 0, it just exists immediately if the thread is not over yet.
You can find many examples on the web of threads. The only special feature, if you are using ADO connections inside the Thread, is that you can't share the same connection.
Each thread must create its own connection, otherwise they are equal (should follow the same rules as any other thread.)
An sample that I have used is this:
TADOSQLThread = class(TThread)
private
FADOQ: TADOQuery; // Internal query
FSQL: string; // SQL To execute
FID: integer; // Internal ID
public
constructor Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
destructor Destroy; override;
procedure Execute(); override;
property ID:integer read FID write FID;
property SQL:string read FSQL write FSQL;
property ADOQ:TADOQuery read FADOQ write FADOQ;
end;
The Create constructor is overrided, and look like this:
constructor TADOSQLThread.Create(CreateSuspended:Boolean; AConnString:String;
ASQL:string; IDThread:integer);
begin
inherited Create(CreateSuspended);
// ini
Self.FreeOnTerminate := False;
// Create the Query
FADOQ := TAdoquery.Create(nil);
// assign connections
FADOQ.ConnectionString := AConnString;
FADOQ.SQL.Add(ASQL);
Self.FID := IDThread;
Self.FSQL:= ASQL;
end;
And the execute method is very simple:
procedure TADOSQLThread.Execute();
begin
inherited;
try
// Ejecutar la consulta
Self.FADOQ.Open;
except
// Error al ejecutar
...Error treattement
end;
end;
To start and create a thread you can use code similar to this:
//crear el Thread
th := TADOSQLThread.Create(True, mmConnection.Lines.Text, ASQL, AId);
// internal for me (for controled the number of active threads and limete it)
inc(numThreads);
// evento finalizacion
th.OnTerminate := TerminateThread;
// Ejecutarlo
th.Resume;
I have create a TerminateThread method that receive the control of threads when they finish. The only different to other threads is the connection problem. You must create a new connection on every thread, It can't share the same ADOConnections with others.
I hope this example will be useful for you.
Regards