I am trying to run 8 threads making IdTCPClient repeatedly scanning a range of IP. When these threads are running, the main form is hanging, lagging. The "IdTCClient.connect" is the issue. Is there a way to fix that ?
unit Unit3;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TTcpThread = class(TThread)
Idx: word;
procedure Execute; override;
end;
TForm3 = class(TForm)
procedure FormShow(Sender: TObject);
private
public
end;
var
Form3: TForm3;
implementation
uses IdTCPClient;
{$R *.dfm}
procedure TTcpThread.Execute;
begin
for var i := Idx*8 to (Idx*8) + (8-1) do // 8 IP per Thread
begin
var TCP := TidTCPClient.Create(nil);
TCP.Host := '192.168.1.' + i.ToString;;
TCP.Port := 9999;
TCP.ConnectTimeout := 500;
TCP.ReadTimeout := 1000;
try
TCP.Connect;
TCP.Disconnect;
except end;
TCP.Free;
end;
end;
procedure TForm3.FormShow(Sender: TObject);
begin
for var i := 0 to 32-1 do // 32 Threads
begin
var Thread := TTcpThread.Create(True);
Thread.Idx := i;
Thread.FreeOnTerminate := True;
Thread.Start;
end;
end;
end.
The mainform will freeze/lag while the threads are running
Related
Below I have some code. What I want to happen is when a button is pressed it creates, or closes, a MIDI connection depending on the state of an existing connection.
But, when attempting to close the MIDI handle I get an error response code 5, which means an invalid handle to a MIDI device has been passed to midiInClose.
I'm not sure why this is happening by my guess is scope issues? I just can't figure out how to resolve this. Should the hMidiIn be defined as a class variable within the form?
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.UITypes, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
MMSystem, uMIDI;
type
TForm2 = class(TForm)
MidiInputCombo: TComboBox;
Label1: TLabel;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
IsConnected: Boolean = False;
SelectedMidiInputID: Integer = 0;
hMidiIn: PHMIDIIN;
implementation
{$R *.dfm}
procedure MidiInProc(hmi: PHMIDIIN; wMsg: UINT; dwInstance: DWORD_PTR; dwParam1: DWORD_PTR; dwParam2: DWORD_PTR); stdcall;
begin
// Do something
end;
procedure TForm2.Button1Click(Sender: TObject);
var
MidiInCloseResult: Integer;
begin
if IsConnected then
begin
MidiInCloseResult := midiInClose(hMidiIn^);
if MidiInCloseResult = MMSYSERR_NOERROR then
begin
IsConnected := False;
Button1.Caption := 'Connect';
end
else
MessageDlg('Response: ' + IntToStr(MidiInCloseResult), mtInformation, [mbOk], 0, mbOk);
end
else
if midiInOpen(#hMidiIn, SelectedMidiInputID, DWORD_PTR(#MidiInProc), 0, CALLBACK_FUNCTION) = MMSYSERR_NOERROR then
begin
IsConnected := True;
Button1.Caption := 'Disconnect';
end;
end;
procedure TForm2.FormCreate(Sender: TObject);
var
I: Integer;
DevCount: Integer;
Pmic: MIDIINCAPS;
begin
DevCount := MidiInputDeviceCount();
if DevCount > 0 then
for I := 0 to DevCount do
midiInGetDevCaps(I, #Pmic, SizeOf(pmic));
MidiInputCombo.Items.Add(Pmic.szPname);
MidiInputCombo.ItemIndex := SelectedMidiInputID;
end;
end.
I have a problem when my Form1 appear on body of browser window, simply he disappear when I put focus in my Form and the browser window lose focus. How solved it? Any suggestion will welcome.
See image below:
and here is my complete code:
Unit for enumeration of windows (EnumWindowUtil_.pas):
unit EnumWindowUtil_;
interface
uses
Winapi.Windows,
System.SysUtils,
System.Classes;
type
TWindowList = class(TStringList)
private
FAddClassname: Boolean;
public
procedure EnumChildWindows(handle: HWND);
property AddClassname: Boolean read FAddClassname write FAddClassname;
end;
var
wlistChilds: TWindowList;
implementation
function GetWindowClassName(hwnd: HWND): string;
begin
SetLength(Result, 1024);
GetClassName(hwnd, PChar(Result), Length(Result));
Result := PChar(Result);
end;
procedure EnumWindowCallback(hwnd: HWND; lParam: TWindowList); stdcall;
var
buffer: array[0..255] of char;
texto: string;
begin
if (not IsWindowVisible(hwnd)) then
Exit;
SendMessage(hwnd, $000D, 256, Integer(#buffer));
texto := StrPas(buffer);
texto := texto + ':' + GetWindowClassName(hwnd) + ' - ' + Format('%6.6x', [hwnd]) + '/' + IntToStr(hwnd);
lParam.AddObject(texto, TObject(hwnd));
end;
procedure TWindowList.EnumChildWindows(handle: HWND);
begin
Clear;
if Winapi.Windows.EnumChildWindows(handle, #EnumWindowCallback, Integer(Self)) then;
end;
end.
Here is main unit:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, EnumWindowUtil_,
Vcl.StdCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
linha: string;
implementation
{$R *.dfm}
function GetNavigatorHandle(BASE: HWND): HWND;
var
I: integer;
begin
linha:= '';
Result := 0;
wlistChilds := TWindowList.Create;
wlistChilds.AddClassname := True;
wlistChilds.EnumChildWindows(BASE);
for I := 0 to wlistChilds.Count - 1 do
begin
linha := wlistChilds.Strings[I];
if
(Pos('Chrome_Render',linha)>0)then
begin
Result := StrToInt(copy(linha, pos('/', linha) + 1, Length(linha)));
Break;
end;
end;
FreeAndNil(wlistChilds);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
janela, janelaContainer: HWND;
begin
janela := GetForegroundWindow;
janelaContainer := GetNavigatorHandle(Janela);
if janelaContainer = 0 then
begin
Exit;
end;
Winapi.Windows.SetParent(form1.handle,janelaContainer);
end;
end.
I have a main form with a progress indicator on it.
In the datamodule I've ten datasets, each of them has an OnBeforeOpen event defined.
I would like to show through the progress bar in the main form a percentage of progress of the opened datasets.
Since I'm completely new to multithreading programming, can someone please give me some advice?
Thank you very much
Either post a message from the thread to the main thread and update the progress bar from there or use the TThread.Queue method to execute some code in the context of the main thread.
unit Unit12;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
const
WM_UPDATE_PB = WM_USER;
type
TForm12 = class(TForm)
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
procedure WMUpdatePB(var msg: TMessage); message WM_UPDATE_PB;
end;
var
Form12: TForm12;
implementation
{$R *.dfm}
procedure UpdateFromThreadViaMessage;
var
i: integer;
begin
for i := 1 to 100 do begin
Sleep(20);
PostMessage(Form12.Handle, WM_UPDATE_PB, i, 0);
end;
end;
procedure UpdateFromThreadViaQueue;
var
i: integer;
begin
for i := 1 to 100 do begin
Sleep(20);
TThread.Queue(nil,
procedure begin
Form12.ProgressBar2.Position := i;
end);
end;
end;
procedure TForm12.Button1Click(Sender: TObject);
begin
TThread.CreateAnonymousThread(UpdateFromThreadViaMessage).Start;
TThread.CreateAnonymousThread(UpdateFromThreadViaQueue).Start;
end;
procedure TForm12.WMUpdatePB(var msg: TMessage);
begin
ProgressBar1.Position := msg.WParam;
end;
end.
After suffering through the same problems as others did, I came up with this solution to previewing/printing Crystal Reports XI reports. This borrows a few lines for the login sequence. I still can't find anything in the *TLB.pas files that allows me to login to the server directly rather than running down through the list of tables. Anyway, here's what I have at this point. Hope it helps someone !
Unit CrystalReports;
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.OleCtrls, ActiveX, ComObj, Data.DB, Data.Win.ADODB,
CrystalActiveXReportViewerLib11_TLB, Vcl.OleServer, CrystalReportsControllersLib_TLB;
type
TCrystalReportForm = class(TForm)
CRV: TCrystalActiveXReportViewer;
procedure DisplayReport;
private
{ Private declarations }
public
{Public declarations }
ReportName : WideString;
ReportCaption : String;
ReportSelectionFormula : WideString;
end;
var
CRXIRuntime : Variant;
implementation
{$R *.dfm}
procedure TCrystalReportForm.DisplayReport;
var
CrystalReport : variant;
i : integer;
begin
CrystalReport := CRXIRuntime.OpenReport(ReportName);
for i := 1 to CrystalReport.Database.Tables.Count do begin
CrystalReport.Database.Tables[1].ConnectionProperties.Item['User ID'] := 'user';
CrystalReport.Database.Tables[1].ConnectionProperties.Item['Password'] := 'password';
end;
CrystalReport.FormulaSyntax := 0;
Caption := ReportCaption;
CrystalReport.RecordSelectionFormula := ReportSelectionFormula;
CRV.Align := alClient;
CRV.ReportSource := CrystalReport;
WindowState := wsMaximized;
CRV.ViewReport;
ShowModal;
end;
begin
CRXIRuntime := CreateOleObject('CrystalRuntime.Application');
end.
Just learning some OpenGL with delphi and trying something simple but not getting a result, I belive i should get a dark green form. But when i run this i get nothing. No errors either. maybe missing something?
unit First1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls,OpenGL, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm2 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
{ Private declarations }
GLContext : HGLRC;
ErrorCode: GLenum;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.FormCreate(Sender: TObject);
var
pfd: TPixelFormatDescriptor;
FormatIndex: integer;
begin
fillchar(pfd,SizeOf(pfd),0);
with pfd do
begin
nSize := SizeOf(pfd);
nVersion := 1; {The current version of the desccriptor is 1}
dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL;
iPixelType := PFD_TYPE_RGBA;
cColorBits := 24; {support 24-bit color}
cDepthBits := 32; {depth of z-axis}
iLayerType := PFD_MAIN_PLANE;
end; {with}
FormatIndex := ChoosePixelFormat(Canvas.Handle,#pfd);
SetPixelFormat(Canvas.Handle,FormatIndex,#pfd);
GLContext := wglCreateContext(Canvas.Handle);
wglMakeCurrent(Canvas.Handle,GLContext);
end; {FormCreate}
procedure TForm2.FormDestroy(Sender: TObject);
begin
wglMakeCurrent(Canvas.Handle,0);
wglDeleteContext(GLContext);
end;
procedure TForm2.FormPaint(Sender: TObject);
begin
{background}
glClearColor(0.0,0.4,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
{error checking}
errorCode := glGetError;
if errorCode<>GL_NO_ERROR then
raise Exception.Create('Error in Paint'#13+
gluErrorString(errorCode));
end;
end.
Since you request a single buffered context, you must call glFinish at the end of the rendering code, to commit your drawing commands to the implementation. However I strongly suggest you switch to using a double buffered context and instead of glFinish-ing you issue a wglSwapBuffers which implies a finish.