Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / General / July 2008



Tip: Looking for answers? Try searching our database.

Help understanding Threading and Blocking Behaviour

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Simon Woods - 24 Jul 2008 17:08 GMT
Hi

I am trying to develop a simple thread server using

http://www.vbaccelerator.com/home/Vb/Code/Libraries/Threading/Multi-threading_us
ing_classes_in_ActiveX_EXEs/article.asp


(I've pasted the code at the bottom of this just-in-case)

I have a simple form with 3 buttons and 3 text boxes. I want to create 3
processes on 3 threads so that all of the text boxes are updated
simultaneously.

So I've tried to wrap up the VBAccelerator's approach a bit. I've
introduced an IProcess public interface inside a ThreadServer
activeX.exe. Ideally I'd be able to implement this on any class in
others project to be able to run several instances of that class on
different threads. This interface requires the inheriting class to
receive a CThread Object.

So I have a Worker class with the following code

++++ MyWorker.Cls ++++

Implements MyThreadServer.IProcess

Public Event WorkerWorking(ByVal Value As Long)

Private m_oThread               As IfxThreadServer.CThread

Private m_bCancel               As Boolean
Private m_nCounter              As Long

Private Sub Class_Terminate()
    Set m_oThread = Nothing
End Sub

Private Sub IProcess_Terminate()
    m_bCancel = True
End Sub

Private Sub IProcess_Run()
    StartCounting
End Sub

Private Property Set IProcess_Thread(ByVal RHS As IfxThreadServer.CThread)
    Set m_oThread = RHS
End Property

Private Sub StartCounting()

    Dim i As Long

    Do While True
        If i > 10000000 Then i = 0
        If m_bCancel Then Exit Do
        i = i + 1
        If i Mod 1000 = 0 Then
            DoEvents
            RaiseEvent WorkerWorking(i)
        End If
    Loop

End Sub

What is happening is that the threads are starting up correctly but only
one of the text boxes is being updated at a time. As soon as I stop that
thread, then the second one begins. The processes are obviously queue up
and ready to run fine, but I am effectively trapped in the loop in the
StartCounting proc.

Is my problem that I am calling back into my worker class which is in a
activeX dll to do the work rather than doing it in the CThread class. If
so, is there another way to do this more generically, so all I need to
do is inherit and interface and/or instantiate a class. Or is there some
other deeper problem going on which I'm not aware of.

I hope that's sufficiently clear.

Many thanks

Simon

Here's the other salient code:

++++  CThreadManager.Cls ++++

Public Function CreateThreadedProcess(ByVal p_oProcess As IProcess) As
IProcess

    Dim l_oThread As CThread

    Set l_oThread = New CThread

    Set p_oProcess.Thread = l_oThread
    l_oThread.Start p_oProcess

    Set CreateThreadedProcess = p_oProcess

End Function

++++  CThread.Cls ++++

Implements Runnable

Private m_oProcess      As IProcess

Private m_bRunning      As Boolean

Public Sub Start(ByVal p_oProcess As IProcess)

   If Not m_bRunning Then
      m_bRunning = True

      Set m_oProcess = p_oProcess

      ' Call the mStart module.  This uses a timer to
      ' fire the Runnable_Start() implementation,
      ' which ensures we yield control back to the
      ' caller before the processing starts.  This
      ' ensures that the processing runs asynchronously
      ' to the client.  Easy!!!
      MThread.Start Me
   Else
      ' Just checking....
      Err.Raise 32540, App.EXEName & ".CThread", "Already running."
   End If

End Sub

Private Sub Runnable_Start()

    m_oProcess.Run

    m_bRunning = False

End Sub

++++ MThread.bas ++++

' To prevent object going out of scope whilst the timer fires:
Private Declare Function CoLockObjectExternal Lib "ole32" ( _
      ByVal pUnk As IUnknown, ByVal fLock As Long, _
      ByVal fLastUnlockReleases As Long) As Long

' Timer API:
Private Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, _
      ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc
As Long) _
      As Long
Private Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, _
      ByVal nIDEvent As Long) As Long

' Collection of Runnable items to start:
Private m_colRunnables As Collection
' The ID of our API Timer:
Private m_lTimerID As Long

Private Sub TimerProc(ByVal lHwnd As Long, ByVal lMsg As Long, _
         ByVal lTimerID As Long, ByVal lTime As Long)
   Dim this As Runnable
   ' Enumerate through the collection, firing the
   ' Runnable_Start method for each item in it and
   ' releasing our extra lock on the object:
   With m_colRunnables
      Do While .Count > 0
         Set this = .Item(1)
         .Remove 1
         this.Start
         'Ask the system to release its lock on the object
         CoLockObjectExternal this, 0, 1
      Loop
   End With
   ' Remove the timer:
   KillTimer 0, lTimerID
   m_lTimerID = 0
End Sub

Public Sub Start(this As Runnable)
   ' Ask the system to lock the object so that
   ' it will still perform its work even if it
   ' is released
   CoLockObjectExternal this, 1, 1
   ' Add this to runnables:
   If m_colRunnables Is Nothing Then
      Set m_colRunnables = New Collection
   End If
   m_colRunnables.Add this
   ' Create a timer to start running the object:
   If Not m_lTimerID Then
      m_lTimerID = SetTimer(0, 0, 1, AddressOf TimerProc)
   End If
End Sub
Tony Proctor - 25 Jul 2008 13:26 GMT
I haven't used this thread support here Simon (I roll my own) but I have a
couple of obvious questions:-

1) Are you seeing this in the IDE or in a compiled EXE? The IDE forces
everything to happen on the main thread so you're not really seeing
multi-threading in action then

2) I can't see any code in your post that "updates a TextBox". Have you
tried some other sort of progress logging, e.g. to files, just to eliminate
any influence by the screen update - which would occurs on the main thread

   Tony Proctor

> Hi
>
[quoted text clipped - 187 lines]
>    End If
> End Sub
Simon Woods - 28 Jul 2008 08:23 GMT
Thx Tony for replying

> I haven't used this thread support here Simon (I roll my own) but I have a
> couple of obvious questions:-
>
> 1) Are you seeing this in the IDE or in a compiled EXE? The IDE forces
> everything to happen on the main thread so you're not really seeing
> multi-threading in action then

Yes ... I'm just performing this in the ide! I haven't tried running
compiled

> 2) I can't see any code in your post that "updates a TextBox". Have you
> tried some other sort of progress logging, e.g. to files, just to eliminate
> any influence by the screen update - which would occurs on the main thread

OK. I'll try that.

I suppose I'm wondering though ... even if I am starting some sort of
ThreadManager.ThreadClass on an ActiveX exe (using the VBAccelerator
timer method) but then calling back into a DLL on an interface (exposed
by the ActiveX exe but implemented by a class in the dll), whether in
fact the processing DLL will cause blocking and the 'stuff' I need to
multithread/task (populating a grid in this instance) actually has to be
housed within the ActiveX exe. I was hoping for a more generic
implementation.

Thx again.
Tony Proctor - 28 Jul 2008 10:27 GMT
I've had issues like this before. If your ActiveX EXE is running in the IDE
then it is forced to execute on a single thread. This means that all your
COM calls, the initial timer, etc., are all behaving in an entirely
different fashion to when running in the compiled EXE, and they depend on
messaging to show some semblance of co-operative execution. If you're using
mutexes/semaphores to implement synchronisation then you could easily block
yourself from executing. Best to skip then using an "am I in the IDE" test
(there are well-known functions posted for doing this)

Since the IDE is precious little use for debugging a multi-threaded ActiveX
EXE (or even a DLL running in a multi-threaded environment like ASP), I
relied on progress messages to a central log file to show the paths through
the code, and any problems encountered. The log recorded the App.ThreadID
and the current time (as close to 'ms' resolution as I could) on every
message. This thread-safe logging code is posted somewhere on the
newsgroups, and the time-recording function was re-posted just a few days
ago

   Tony Proctor

> Thx Tony for replying
>
[quoted text clipped - 25 lines]
>
> Thx again.
Simon Woods - 28 Jul 2008 11:21 GMT
Thx again Tony. I'll look up the code you mentioned.

Sorry, though, just for my own clarification (and I think you may have
answered this implicitly when you made reference to ASP), suppose a
class - e.g. ClassA (implementing an IWorkerThread interface) - in a dll
makes a call to an activex exe which creates a new object ("object per
thread" setting is checked) and which is set back into ClassA (via the
IThreadedWorker interface).  Suppose a timer then triggers the thread
object to invoke a method on the ClassA's IWorkerThread (effectively
it's parent class), which threading model is being used, the dll's or
the activex exe's?

> I've had issues like this before. If your ActiveX EXE is running in the IDE
> then it is forced to execute on a single thread. This means that all your
[quoted text clipped - 43 lines]
>>
>> Thx again.
Tony Proctor - 28 Jul 2008 15:36 GMT
All VB components use the STA threading model Simon. This is true of DLLs
(even in an ASP environment) and multi-threaded ActiveX EXE's. It basically
means that each thread has its own data and does not share any data with any
other thread. In your ActiveX EXE then this effectively means that data in a
Module (as opposed to a Class) isn't "global" any more - each thread gets
its own copy. On the upside, it means there are no data synchronisation
issues to worry about, unless you're trying to engineer something very
heroic like shared memory with APIs.

I'm not sure whether you're interested in my "ASP" reference because that's
what you're using Simon. There could be other problems here if you're using
ASP. The IIS worker process (w3wp or DLLHOST, depending on which IIS
version) offers a number of threads equal to AspProcessorThreadMax *
processor_count. AspProcessorThreadMax is usually 25. On a single-processor
box, you'd therefore have 25 ASP threads accessing your ActiveX EXE.
However, on a massive 8 processor box, you'd have 200 threads. This is
important if those ASP threads are memory-hungry since their virtual memory
all comes from the same process. That process has a theoretical limit of 2Gb
of user virtual address space, but a more realistic limit of about 1.8Gb
when you factor in 'heap fragmentation' issues.

One thing that jumps out at me here would be any attempt to launch
asynchronous processing in the ActiveX EXE. IIS (& hence ASP) is
"stateless", meaning that any given thread will be handling someone else's
request as soon as it's finished with yours. They can't therefore expect to
receive a completion event from something started while handling a previous
request. In fact, I've seen an article that certain event types are just not
supported within IIS. There's no problem with each of the ASP threads
creating and launching independent threads in the ActiveX EXE but they
should wait until those threads have finished what they were doing before
completing in the incoming HTTP request. If they start something
asynchronous, who's going to see the completion of that processing?

P.S. Don't forget that any VB component should have 'Unattended execution'
and 'Retain in memory' set if working within a multi-threaded environment

   Tony Proctor

> Thx again Tony. I'll look up the code you mentioned.
>
[quoted text clipped - 55 lines]
>>>
>>> Thx again.
Simon Woods - 28 Jul 2008 17:02 GMT
Tony, thanks vm for your time, once again.

> All VB components use the STA threading model Simon. This is true of DLLs
> (even in an ASP environment) and multi-threaded ActiveX EXE's. It basically
[quoted text clipped - 4 lines]
> issues to worry about, unless you're trying to engineer something very
> heroic like shared memory with APIs.

I hope I'm not.

So if I have a UI component (implementing an interface) which is
populated by a class (in a dll) via the interface which is in turn being
triggered to get it's data by a timer on a class instantiated in an AX
Exe on it's own thread, are you suggesting that because the AX Exe class
is calling a method of the class from the dll, then the UI component and
dll class effectively get copied across into the process space of AX exe
and get invoked/updated there (and not back in the UI) or would
something stop the UI component getting copied across to the AX Exe?

The examples I've seen of updating UIs on different threads all have the
UI located in the AX Exe. If my case the UI is in an OCX. If copies of
data are held, presumably I could load the data (coming from a dataset)
into, say, several variant arrays in the AX Exe and then access them,
say, via properties on the AX's class and then bind them to the various
UI components back in the DLL/OCX (it's a flexgrid).

However, if I want to populate several grids (or even several variant
arrays) from a dataset in a multi-threaded way, presumably the dataset
would get copied into the AX address space which itself would be rather
slow, wouldn't it?

Alternatively I suppose I could have all the grids in the AX exe and
then re-parent to a window in the main OCX once populated. But perhaps
it may be more performant for the AX exe to actually open the dataset.

I'm sorry if it's taking rather a long time for me to 'get it' and my
thoughts are rather rambling!!. I am trying to understand the various
strategies by which I might be able to improve performance using more
than 1 thread.

> I'm not sure whether you're interested in my "ASP" reference because that's
> what you're using Simon.

No I'm not using ASP, but I wondered whether perhaps some of the
principles are similar. I don't think this is as important as trying to
 improve my lack of understanding in other areas!
Tony Proctor - 28 Jul 2008 19:23 GMT
Not sure I follow your convoluted description of the structure Simon :-)

A DLL executes in the process of whichever EXE is referencing it. If it's
your ActiveX EXE that's referencing the DLL then it is part of that ActiveX
EXE process. This means that any data in a Module belonging to either of
those projects (the EXE or DLL) will be duplicated for each of its threads.
In other words, each thread of the ActiveX EXE will have its own private
copy of that data and will not be sharing it with any of the other threads.
This is quite easy to demonstrate (but not in the IDE of course), and it may
affect your intended design.

Technically speaking (i.e. according to MSDN), a multi-threaded VB6
component should set those options I mentioned. However, if you set
'Unattended execution' then the project cannot include any Forms or Controls
and that would snooker you in a fundamental way. If the author of your
threading support is Olaf (aka Schmidt) then I'm sure he's thought of this.
However, I've not used that code myself.

   Tony Proctor

> Tony, thanks vm for your time, once again.
>
[quoted text clipped - 45 lines]
> principles are similar. I don't think this is as important as trying to
> improve my lack of understanding in other areas!
Schmidt - 28 Jul 2008 21:43 GMT
> If the author of your threading support is Olaf ...
Don't know - Simon is talking about an AX-Exe-
approach and maybe he's using one of my AX-Exe-
Threading-Demos as a starting-point (but not sure).

My tools with builtin VB6-Threading-support don't
use AX-Exes, they need AX-Dlls as the Hosting-
Binaries for the Public "ThreadClasses" and are usable
in a VB-Std-Exe.

Anyway ... @Simon:
I think you should confine your case somewhat
and define one single "goal".
e.g. based on your Grid-Filling.

Describe the current situation ... the time it takes to
fill your grid currently, the type of query, the number of
Columns and Records, the used DB-Backend, the used
DB-Access-Layer (ADO or DAO - maybe ADOs async-
fetching can do fine here ... or an optimized Query with
proper Indexes). And if you possibly have some Grid-
Alternatives at hand (the MS-FlexGrids are somewhat
"crippled" in terms of their binding-capabilities for DB-Data -
the ComponentOne-pendants for example offer nicer interfaces,
to implement async DataBinding).

Threading in VB6 can be done in many different ways -
some approaches easier than the other - that's why it
is better, to focus on a more concrete scenario, to be
able to recommend something useful - and maybe you can
avoid threading completely, which is not the worst idea. ;-)

Olaf
Simon Woods - 29 Jul 2008 14:24 GMT
>> If the author of your threading support is Olaf ...
> Don't know - Simon is talking about an AX-Exe-
[quoted text clipped - 21 lines]
> the ComponentOne-pendants for example offer nicer interfaces,
> to implement async DataBinding).

OK.

The recordset (it is a data layer wrapping ADO/RDO/DAO) is returning
approx 2500 rows and 30 columns. It takes about 60 secs to populate. (I
timed a grid loading that much data from an ado dataset and it took a
few seconds on my machine. The fundamental bottleneck is that I have to
format/process, in some way, virtually every piece of data returned via
the dataset and unfortunately I can't do this server-side. If I just
load all the raw (i.e. untranslated data), it still takes about 12 secs
just to get into the grid. However, I need to do this translation
process at least for the visible data. At the moment, I've implemented a
mechanism which only translates the data in the viewport and as the grid
is scrolled/resized etc.

I will no doubt have to look into speeding up this in due course, but
for the time being I have to leave that as is. So I am looking for other
ways to reduce user-wait-time while the grid is loading.

However, this speed up is offset when I need to do certain tasks with
the grid e.g. sorting, exporting, charting etc etc, when all the data
needs to be present and formatted correctly. For that reason I thought a
background load (rather than a load-on-demand) to get all the data into
the grid as soon as possible seemed a better approach. The problem gets
compounded further when I need to load data from the dataset into
several grids to display hierarchical nature of the data returned.

So that's the situation. Do you think threading is the wrong way to go?

Thx

S
Schmidt - 29 Jul 2008 19:42 GMT
> OK.
>
> The recordset (it is a data layer wrapping ADO/RDO/DAO) is
> returning  approx 2500 rows and 30 columns.
Ok, seems not all that much data.
E.g. the "Select * From Invoices"-call against NWind.mdb
delivers 26 Columns on 2155 Rows and this is a relative
complex Join, defined as a View inside the *.mdb.

Retrieving the appropriate ADO-Rs from 'c:\NWind.mdb'
needs ca. 100msec (repeated calls, Cnn.Cursorlocation=
adUseClient and the Rs retrieved with adOpenStatic and
adLockBatchOptimistic).
Another 60msec are needed, to bind that prefilled ADO-Rs
to a MS-HFlexGrid. The HFlex does not show the fastest
behaviour in this case, since it needs these 60msec, to loop
over the Rs-Data, making a copy for each Field-Value (e.g.
the MS-Datagrid does better in this regard, since it does not
make any copies for its Cells, but visualizes only its currently
visual Rows and Columns directly from the "untouched" Rs-
Content).
But anyway, you apparently need the FlexGrid and you are
proably using it in unbound Mode, after preparing your Rs-
Data.
Don't know, if you are aware of the Clip-Property of the
FlexGrid, which is the fastest way, to pump Data into that
Grid.
Don't even think about using the TextMatrix-Property
if you want to achieve a fast filling of the Flex-Cells.

> It takes about 60 secs to populate.
That's far too much of course.
If I understand you correctly 12 of these seconds aree needed,
only to fill up the plain and untouched ADO-Recordset from
the DB - is that right?
If yes, that amount of time already seems a bit much, even if
there's a network between your Client and the DB-Backend.

The other 48 seconds (preparing Rs-Data and filling up
the Grid) worth looking at too - the appropriate clientside
routine should be changeable with ease, to achieve a much
better performance.

> So that's the situation. Do you think threading is the wrong
> way to go?
It seems your performance-issue is mainly at the clientside -
and threading would not be of much use, since you will have
to process your data in either way, to be able to work with
the formatted data as intended.
Threading for CPU-related tasks makes only sense, if you
have multiple CPUs (CPU-Cores) available at the clientside.
Threading on a single-core just to give the User an illusion
of speed does not worth the effort - better to invest that
time into better algos or a better structured "workflow".

Anyway, here comes a Demo for fast filling a FlexGrid
in unbound-Mode, based on the NWind.mdb Invoices-
View, looping over the retrieved ADO-Rs completely,
and building a Rows-StringArray the fast way, so that
we can make use of the FlexGrids Clip-Property.
The Rs-Select needs ca. 100msec and the Loop
over the Rs, preparing the Rows-StringArray and
filling up the Grid needs another ca. 110msec, suming
up to a total time of 210msec for 2155Rows and 26Cols):

'***Into a Form (needs a HFlex, named FG and a
'reference to ADO - and a copy of NWind.mdb,
'located at c:\NWind.mdb
Option Explicit

Private Cnn As Connection

Private Sub Form_Load()
 Set Cnn = New ADODB.Connection
 Cnn.CursorLocation = adUseClient
 Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\NWind.mdb"
End Sub

Private Sub Form_Click()
Dim i&, j&, V, Rs As Recordset, Rows$(), Cols$(), T!

 T = Timer

 Set Rs = New ADODB.Recordset
 Rs.Open "Select * From Invoices", Cnn,adOpenStatic,adLockBatchOptimistic

 Caption = Timer - T & " (Rs-Select), "

 FG.Redraw = False 'switch Redraw of tempoarily

   'set the Row- and Col-Counts (one more for Headers)
   FG.Cols = Rs.Fields.Count + 1
   FG.Rows = Rs.RecordCount + 1

   For i = 1 To Rs.Fields.Count 'set the Col-Headers
     FG.TextMatrix(0, i) = Rs.Fields(i - 1).Name
   Next i

   'now the Array-Preparing for using the Clip-Prop
   ReDim Rows(0 To Rs.RecordCount - 1)
   ReDim Cols(0 To Rs.Fields.Count - 1)

   '...and the Fill-Routine for the Rows-StringArray
   i = 0
   Do Until Rs.EOF
     With Rs.Fields
       For j = 0 To .Count - 1
         V = .Item(j).Value
         If IsNull(V) Then Cols(j) = "" Else Cols(j) = V

         'just an additional check, if some Values contain CrLfs
         'we replace them with vbLF, since the Clip-Property expects
         'vbCrs as Record-Delimiter
         If InStr(Cols(j), vbCrLf) Then
           Cols(j) = Replace(Cols(j), vbCrLf, vbLf)
         End If
       Next j
     End With
     Rows(i) = Join(Cols, vbTab)
     i = i + 1
     Rs.MoveNext
   Loop

   'transfer the Rows-Array into the Grid
   FG.Row = 1: FG.Col = 1
   FG.RowSel = FG.Rows - 1: FG.ColSel = FG.Cols - 1
     FG.Clip = Join$(Rows, vbCr)
   FG.Row = 1: FG.Col = 1

 FG.Redraw = True
 Caption = Caption & Timer - T & " (total time)"
 Rs.Close
End Sub

Olaf
Simon Woods - 30 Jul 2008 06:25 GMT
<snip>

OK ... this looks interesting. I'll have a play.

Thx very much to you both for your time and thoughts.
Schmidt - 30 Jul 2008 12:10 GMT
> <snip>
>
> OK ... this looks interesting. I'll have a play.
Just let me know, how you come along with reducing
your 48sec TransformRsDataAndFillFlexGrid-
Routine. With the approach using the .Clip-Prop
you should achieve (even with more "transforming-effort"
at your side) fill-times of below 2sec - if not, just post
the most timeconsuming part of your transform-routine -
I'm sure someone will jump on this topic here.

Olaf
Simon Woods - 30 Jul 2008 18:19 GMT
>> <snip>
>>
[quoted text clipped - 8 lines]
>
> Olaf

Olaf

Just to say that the "Clip" approach reduced the load time to just over
1 sec. which was great.

There is still bottleneck because at some stage, e.g. prior to exporting
the contents of the grid, I have to make sure that all cells are
formatted. Calls to format a particular cell can take up to 2ms which
when your dealing with 30x2500 cells can mount up. The bottle neck is
caused by an object in the data layer over which I have little control.
At the moment it can take 25secs to format the grid. So I'm having to
try and hide the lag by distributing the delay through formatting the
grid data on demand rather as en masse.

Unless, that is, you have other suggestions ....

Thx again

S
Schmidt - 30 Jul 2008 19:18 GMT
> Just to say that the "Clip" approach reduced the load time
> to just over 1 sec. which was great.
Ah, glad you figured that part out.

> There is still bottleneck because at some stage, e.g. prior to exporting
> the contents of the grid, I have to make sure that all cells are
> formatted. Calls to format a particular cell can take up to 2ms which
> when your dealing with 30x2500 cells can mount up. The bottle neck is
> caused by an object in the data layer over which I have little control.
Little control sounds bad... ;-)
Normally (as already demonstrated somewhat in the .Clip-approach)
you should format complete areas of your Grid in larger chunks
(e.g. complete Columns) by prior selecting of the appropriate
ranges (per RowSel, ColSel).

If you have no access to the formatting-code, then this is
of course difficult - maybe you can simply ignore the other
formatting-routine (comment out) and write your own
instead, using larger ranges (complete Rows or Columns)?

Olaf
Larry Serflaten - 25 Jul 2008 15:36 GMT
> I am trying to develop a simple thread server using
>
[quoted text clipped - 5 lines]
> processes on 3 threads so that all of the text boxes are updated
> simultaneously.

Regardless of how it appears, a single CPU can only execute on a single
thread basis.  That is to say it is only going to execute instructions from
one thread, at a time.  The CPU can be made to jump between multiple
threads, to achieve the effect of multithreading, but it still only operates
on one thread at a time. (assuming a single core processor)

The OS takes care of switching between the threads, which might more
accurately be called multi-tasking because several different tasks are
'seemingly' performed at the same time.  But again, they can only be
switched in and out one at a time, very rapidly, in the single core scenareo.

If you are trying to address a multi-core processor, you should know
that your Form can only live on one thread, only one command to fill
a textbox will be allowed at a time, therefore your textboxes have to be
updated in serial fashion (one at a time).

If you are trying to do some asyncronous tasks, you could develop
a multi-tasking engine to do those tasks in piecemeal fashion. For an
example of multi-tasking (or background processing) have a look at
this article: http://www.devx.com/vb2themax/Article/19890/0

Do you really want multiple threads, or would multi-tasking suit
your needs?

LFS
Tony Proctor - 25 Jul 2008 15:49 GMT
This description of what "multi-tasking" means should be irrelevant Larry.
The O/S ensures that each thread gets an appropriate time-slice. Hence, even
if those threads are compute-bound and never call DoEvents then they should
still (apparently) operate in parallel. If this is not happening then it is
very likely that they're operating on a single thread (as with my IDE
suggestion), or there is some cross-thread blocking going on (as in my 2nd
suggestion)

   Tony Proctor

>> I am trying to develop a simple thread server using
>>
[quoted text clipped - 34 lines]
>
> LFS
Larry Serflaten - 25 Jul 2008 16:20 GMT
> This description of what "multi-tasking" means should be irrelevant Larry.

I made the distinction to avoid confusion.  Multithreading happens at the OS level,
which takes care of switching the threads in and out.  Multi-tasking (can be
at the OS level) was mentioned to differentiate it as being a similar operation but
at the application level. Mutli-tasking can be accomplished on a single thread,
mutli-threading (obviously) cannot.

That was the reason for the differentiation, so the OP can decide which path
he really wants to follow....

LFS
Tony Proctor - 25 Jul 2008 16:31 GMT
Hmm, I think we may be using terms different to each other Larry

All modern O/S's "multi-task" (i.e. make things happen - or appear to
happen - in parallel). Sometimes the hardware offers multiple processes, or
multiple processor cores, in order to make this more efficient. However, the
kernel is still scheduling multiple threads (not processes) across the
available hardware resources and ensuring they get a fair crack of the whip.
A "thread" is therefore the fundamental unit of this scheduling.

You can actually multi-task on a single-thread using a timer. Some old
threading libraries used to work like this.

   Tony Proctor

>> This description of what "multi-tasking" means should be irrelevant
>> Larry.
[quoted text clipped - 14 lines]
>
> LFS
Simon Woods - 28 Jul 2008 08:47 GMT
Thx Larry for responding ...

> If you are trying to do some asyncronous tasks, you could develop
> a multi-tasking engine to do those tasks in piecemeal fashion. For an
> example of multi-tasking (or background processing) have a look at
> this article: http://www.devx.com/vb2themax/Article/19890/0

Okay ... thx.  I've downloaded this and am perusing it. The architecture
is pretty much what I had in mind ... so that's good. Could you explain
why you chose to host the TaskManager element in the main app rather
than in an ActiveX exe? Is it that you were primarily interested in
implementing timesplicing?

> Do you really want multiple threads, or would multi-tasking suit
> your needs?

You perhaps could advise me ...

I've identified perhaps 2 parts of my app which may benefit from
multithreading/tasking. I have several grids which need to display a
load of data. (There's a hierarchical relationship between data in each
grid). At the moment I am loading the data then displaying, but for
large amounts of data it is proving just too slow. So, the first
application of multithreading/tasking would be to to load a few rows for
each grid and then display but keep loading 'in background'. Secondly,
the grids all need to be loaded together and my initial thought was to
load each grid on a separate thread.
Simon Woods - 28 Jul 2008 10:18 GMT
> Thx Larry for responding ...
>
[quoted text clipped - 8 lines]
> than in an ActiveX exe? Is it that you were primarily interested in
> implementing timesplicing?

On re-reading my post (and your article), I think I have probably
understated the intention behind and techniques used in your article,
Larry. If I have, then I'm sorry. It is purely due to my lack of
understanding.

Thx for you help again.
Larry Serflaten - 28 Jul 2008 13:41 GMT
> > If you are trying to do some asyncronous tasks, you could develop
> > a multi-tasking engine to do those tasks in piecemeal fashion. For an
[quoted text clipped - 6 lines]
> than in an ActiveX exe? Is it that you were primarily interested in
> implementing timesplicing?

Because many of the tasks that I envisioned involved accessing the
demo form and its controls.  The idea was to 'get the feel' for writing
tasks that worked in piecemeal fashion.  If you put that in an EXE, you'd
invoke cross-process marshalling of data and other slow downs, but
it would be possible.

> > Do you really want multiple threads, or would multi-tasking suit
> > your needs?
[quoted text clipped - 4 lines]
> multithreading/tasking. I have several grids which need to display a
> load of data.

As you may have seen, the listbox was filled with sequential numbers
in a lazy fashion.  Filling your grids in a similar manner would be one
adaptation of that idea....

LFS
Simon Woods - 28 Jul 2008 17:03 GMT
>>> If you are trying to do some asyncronous tasks, you could develop
>>> a multi-tasking engine to do those tasks in piecemeal fashion. For an
[quoted text clipped - 23 lines]
> in a lazy fashion.  Filling your grids in a similar manner would be one
> adaptation of that idea....

Yes ... that is food for thought.

Thx vm again, Larry.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.