Help understanding Threading and Blocking Behaviour
|
|
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.
|
|
|