Delphi Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming Languages - MoreDelphi Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old June 9th, 2009, 08:54 AM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
Question Multithreading in Libraries using ADO

Hi;
I'm creating an application which connects to some medical instruments and gathers data. The application itself does nothing more than looking in a designated folder to load instruments. Each instrument is encapsulated in a DLL, and has a function which loops and reads the RS232 port, and write the data to a MSSQL2000 database. Because of this loop, which looks like this:
repeat
Sleep(500);
GetDataFromPort;
ParseData;
if AbortLoop then // AbortLoop is set by a button on a form
Break;
until False;
the application is almost completely blocked, and the CPU usage is about 100 %. I'm looking for a way to run each loop in a separate thread.
I have a simple problem. "CoInitialize() has not been called"
I have called it in my host application, and in my library. But I'm still getting this error. Any Idea?

Reply With Quote
  #2  
Old June 9th, 2009, 12:40 PM
th0r1000 th0r1000 is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2009
Posts: 6 th0r1000 User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 8 m 25 sec
Reputation Power: 0
From what I can tell from that piece of code you are in a loop that will in fact take up a lot of processing on the CPU, I would rather use a timer component and put that code in the trigger method excluding the repeat..until part.

Reply With Quote
  #3  
Old June 9th, 2009, 01:20 PM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
I cannot do that because it would require me to modify the code of about 95 libraries. That's why I'm trying to spawn each library in a new thread in the host application

Reply With Quote
  #4  
Old June 9th, 2009, 02:57 PM
clivew clivew is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2006
Location: Carlsbad, CA
Posts: 1,124 clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 6 Days 1 h 39 m 23 sec
Reputation Power: 272
Quote:
I cannot do that because it would require me to modify the code of about 95 libraries.

Seems like there is something awfully wrong with your code or the components you are using.
What happened to inheritance?

BTW: Why do you think threads will help?
I believe that sleep statement is still going to absorb time.
Are you sure that all your code is thread safe and that the DLLs are re-entrant?

Reply With Quote
  #5  
Old June 9th, 2009, 03:44 PM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
I'm not using any components; I open the ports with CreateFile.
Each library is completely stand alone and thread safe, but I don't know what re-entrant means.

Reply With Quote
  #6  
Old June 9th, 2009, 05:37 PM
clivew clivew is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2006
Location: Carlsbad, CA
Posts: 1,124 clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 6 Days 1 h 39 m 23 sec
Reputation Power: 272
Quote:
Originally Posted by ibiglari
I'm not using any components; I open the ports with CreateFile.
Each library is completely stand alone and thread safe, but I don't know what re-entrant means.

Then I don't understand your environment. Perhaps you can give a more complete explanation.

You said (I thought) that your code was loading instruments contained in third party DLLs.

Can you clarify which is your code, which are the libraries and which are the DLLs
and what you have source to and what you only have an API for.

Perhaps that will help us help you.
What are the gauges measuring?

Reply With Quote
  #7  
Old June 10th, 2009, 01:47 AM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
Quote:
Originally Posted by clivew
Then I don't understand your environment. Perhaps you can give a more complete explanation.

You said (I thought) that your code was loading instruments contained in third party DLLs.

Can you clarify which is your code, which are the libraries and which are the DLLs
and what you have source to and what you only have an API for.

Perhaps that will help us help you.
What are the gauges measuring?

There's no third party library. Both the host application and libraries are mine.

I can not post attachments in here; if you tell me how to send some source files, I'll post the host application and one of the libraries.

Reply With Quote
  #8  
Old June 10th, 2009, 11:20 PM
clivew clivew is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2006
Location: Carlsbad, CA
Posts: 1,124 clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 6 Days 1 h 39 m 23 sec
Reputation Power: 272
Thumbs up

Quote:
Originally Posted by ibiglari
There's no third party library. Both the host application and libraries are mine.

I can not post attachments in here; if you tell me how to send some source files, I'll post the host application and one of the libraries.

I will leave this to someone else.
I am not really getting a feel for what you are doing.
What about the DLLs?
What do you mean by a library?
Is it a unit a class or ??

If they are all yours, why do you have to change 95 of them?
I don't know enough about what you are doing; but it seems like you need to do some serious refactoring with an inheritance tree.

Good luck.

Reply With Quote
  #9  
Old June 11th, 2009, 07:26 AM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
I try to describe my application in more details. Sorry if the information I provided was not clear.

There's a host application named "Transfer.exe". It looks in a folder named "Instruments" for files matching the following pattern: "*.INS". Each ".INS" file is a library which exports this functions:

Code:
function OpenPort(APort: Byte;
                  ABaudRate: Integer;
                  ADataSize: Byte;
                  AParity: Byte;
                  AStopBits: Byte): Boolean; export;

procedure ClosePort; export;

procedure ShowConfigDlg(ADataSource, ADataBase: ShortString); export;

procedure ShowAboutDlg; export;

procedure Communicate(ADataSource, ADataBase: ShortString;
                      APrefix: ShortString; AHandle: HWND;
                      ATimeOut: Cardinal); export;

function GetInstrumentClass: Byte; export;

function GetDescription: ShortString; export;


For each file, the host application creates an instance of a class which is declared like this:
Code:
type
  TGetInstrumentName = function(AAppHandle: HWND): ShortString;
  TGetDescription = function: ShortString;
  TGetInstrumentClass = function: Byte;
  TOpenPort = function(APort: Byte;
                       ABaudRate: Integer;
                       ADataSize: Byte;
                       AParity: Byte;
                       AStopBits: Byte): Boolean;
  TCommunicate = procedure(ADataSource, ADataSet: ShortString; APrefix: ShortString; AHandle: HWND; ATimeOut: Cardinal);
  TClosePort = procedure();
  TShowConfigDlg = procedure(ADataSource, ADataSet: ShortString);
  TShowAboutDlg = procedure;

type
{$IFDEF MultiThread}
  TTransferModule = class(TThread)
{$ELSE}
  TTransferModule = class(TObject)
{$ENDIF}
  private
    LibHandle: HWND;

    _GIN: TGetInstrumentName;
    _GD: TGetDescription;
    _GIC: TGetInstrumentClass;
    _OP: TOpenPort;
    _Comm: TCommunicate;
    _CP: TClosePort;
    _SCD: TShowConfigDlg;
    _SAD: TShowAboutDlg;
  public
    LibFile: String;
{$IFDEF MultiThread}
    procedure Execute; override;
{$ELSE}
    procedure Execute;
{$ENDIF}

    function GetInstrumentName: ShortString;
    function GetDescription: ShortString;
    function GetInstrumentClass: Byte;
    function OpenPort(APort: Byte;
                      ABaudRate: Integer;
                      ADataSize: Byte;
                      AParity: Byte;
                      AStopBits: Byte): Boolean;
    procedure ClosePort;
    procedure ShowConfigDlg;
    procedure ShowAboutDlg;
    constructor Create(ALibFile: String);
  end;


Each function has a body which looks like this:
Code:
procedure TTransferModule.ShowAboutDlg;
begin
  @_SAD := GetProcAddress(LibHandle, 'ShowAboutDlg');
  _SAD;
end;


When the user invokes the Communicate command in the host application, this code is executed:
Code:
procedure TdlgTransfer.btnConnectClick(Sender: TObject);
var
  Parity: Byte;
begin
  APrefix := cbSerial.Text;
  ATimeOut := StrToInt(cbTimeOut.Text);

  Parity := NOPARITY;

  case cbParity.ItemIndex of
    1: Parity := EVENPARITY;
    2: Parity := ODDPARITY;
  end;

  if not CurrentModule.OpenPort(cbPort.ItemIndex + 1, StrToInt(cbBaudRate.Text), StrToInt(cbDataSize.Text), Parity, cbStopBit.ItemIndex) then
    raise Exception.Create('Connection Failed');
{$IFDEF MultiThread}
  CurrentModule.Resume;
{$ELSE}
  CurrentModule.Execute;
{$ENDIF}
end;


The communicate function which contains the loop is defined in a library with an extension of ".INS" like this:
Code:
procedure Communicate(ADataSource, ADataBase: ShortString; APrefix: ShortString; AHandle: HWND; ATimeOut: Cardinal); export;
var
  AbortLoop: Boolean;

  procedure CallBack(ALine: ShortString);
  var
    CopyData: TCopyDataStruct;
  begin
    with CopyData do
    begin
      dwData := 0;
      cbData := SizeOf(ALine);
      lpData := @ALine;
    end;
    SendMessage(AHandle, WM_USER, dlgResults.Handle, Integer(@COPYDATA));

    Application.ProcessMessages;
    AbortLoop := dlgResults.AbortLoop;
  end;

var
{some local variables}
begin
  dmData := TdmData.Create(nil);
  OldHandle := Application.Handle;
  try
    Application.Handle := AppHandle;
    dmData.OpenConnection(ADataSource, ADataBase);
    AbortLoop := False;
    dlgResults := TdlgResults.Create(nil);
    try
      if not dlgResults.Visible then
        dlgResults.Show
      else
        dlgResults.BringToFront;
      repeat
        Buffer := '';

        FillChar(PR, SizeOf(PR), 0);
        repeat
          CallBack('');
        until (ReadFromSerial(Port, TimeOut) = STX) or AbortLoop;
        if AbortLoop then
          Break;
        repeat
          c := ReadFromSerial(Port, TimeOut);
          if (c <> ETX) and (c <> #0) then
            Buffer := Buffer + c;
          CallBack('');
        until (c = ETX) or AbortLoop;
        if AbortLoop then
          Break;
        WriteToSerial(Port, ACK, TimeOut);
        {process the data}
        MessageBeep(MB_OK);
      until False;
    finally
      ClosePort;
      dlgResults.Release;
    end;
  finally
    CallBack(#27);
    ClosePort;
    dmData.Free;
    Application.Handle := OldHandle;
  end;
end;


Now, if I declare the conditional define MultiThread, I get an error when I try to create my DataModule in the "*.INS" file. The error says "CoInitialize has not been called". I tried to call it at the initialization section of my first unit in the "*.INS" file, but I had no chance.

Hope this makes my question a little more clear

Reply With Quote
  #10  
Old June 11th, 2009, 01:08 PM
clivew clivew is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2006
Location: Carlsbad, CA
Posts: 1,124 clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 6 Days 1 h 39 m 23 sec
Reputation Power: 272
Quote:
I tried to call it at the initialization section of my first unit in the "*.INS" file, but I had no chance.

You need to call it when you initialize each thread and call CoUnInitialize before you close each thread.

A lot of your other code looks very unconventional also.
Not sure why you have all those DLLs or why you suffix them with .INS but that is none of my business.

Reply With Quote
  #11  
Old June 11th, 2009, 04:01 PM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
So I need to call CoInitialize and CoUnintialize in my host application?

Reply With Quote
  #12  
Old June 11th, 2009, 08:22 PM
clivew clivew is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Jan 2006
Location: Carlsbad, CA
Posts: 1,124 clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level)clivew User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 6 Days 1 h 39 m 23 sec
Reputation Power: 272
Quote:
Originally Posted by ibiglari
So I need to call CoInitialize and CoUnintialize in my host application?

In each thread.

Reply With Quote
  #13  
Old June 15th, 2009, 07:03 AM
ibiglari ibiglari is offline
Mr. iMan
Dev Shed Newbie (0 - 499 posts)
 
Join Date: May 2004
Location: Tehran/Iran
Posts: 19 ibiglari User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 4 h 49 m 27 sec
Reputation Power: 0
Send a message via AIM to ibiglari Send a message via MSN to ibiglari Send a message via Yahoo to ibiglari
:-)

I did call CoInitialize() at the beginning of Communicate() procedure, and CoUninitialize() at the finally block. Everything seems to work fine, but I guess I need to send a message back to the host application indicating that the procedure is quitting.
Thank you for your help :-)

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming Languages - MoreDelphi Programming > Multithreading in Libraries using ADO


Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump




 Free IT White Papers!
 
How to Present Effectively Online
This white paper offers practical and actionable advice on the key steps that any presenter should consider as they plan and execute a Webinar or online meeting.

 
Open Source Security Myths
Open Source Software (OSS) is computer software whose source code is available to the general public with relaxed or non-existent intellectual property restrictions (or arrangement such as the public domain), and is usually developed with the input of many contributors.

 
Power and Cooling Capacity Management for Data Centers
This paper describes the principles for achieving power and cooling capacity management.

 
Scalable, Fault-Tolerant NAS for Oracle - The Next Generation
For several years NAS has been evolving as a storage alternative for Oracle databases, and for good reason: NAS is quite often the simplest, most cost-effective storage approach for Oracle. Learn about the benefits that HP's approach to scalable NAS brings to Oracle environments in this comprehensive white paper.

 
Understanding Web Application Security Challenges
This white paper discusses many common threats and preventive measures for Web application security, and explains what you can do to help protect your organization.

 

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 




© 2003-2009 by Developer Shed. All rights reserved. DS Cluster 1 Hosted by Hostway
Stay green...Green IT