06302049.txt 30-Jun-00


GC

From mike@richsoftware.com Fri Mar 17 01:12:32 2000

I'm looking for details of how the garbage collector handles
  multithreaded apps in 2.5. I've found a couple of
  functions in the SDK source for the system library called
  EnterCGCSection() and LeaveCGCSection() which imply that
  it now uses its own critical section. Can anyone add to
  that?

Mike


From geoffsch@bigpond.net.au Fri Mar 17 08:14:27 2000

Mike,

The GC is something the entire Dev Team has been tight
  lipped over, despite repeated requests for details.
Uwe Holz wrote a very informative article in SDT 3/99 and
  although it is big on the "what", it is not big on the
  "how". For example, on Page 20 he explains in "When does
  it Slam" that the GC will kick in automatically when it
  needs to allocate further dynamic memory. Although it can
  be shown situations where this does not happen and
  although it is not written about explicitly, I take this
  to be thread specific. I say this because each thread is
  given its own dynamic memory space.
In fact, I assume all the functions referred to on page 24
  relate only to dynamic memory data in the calling thread.
  I also assume that each thread is also given its own
  static memory (ie heap) space.
About the only "logic" for making these assumptions is that
  CreateGCDump() doesn't show up dynamic variables in a
  parallel thread so I feel I am safe in this assumption.
  Sabo, at TC 99 and a dozen other places is quoted as
  announcing that the GC is "...now threadsafe in VO
  2.5...." but he was equally scathing of the use of GUI
  within a new thread. Despite being questioned publicly and
  privately on this, he has consistently refused to
  elaborate. The position is inconsistent: it is either safe
  or it isn't.
I have done my own work on this and found no particular
  problems with GUI in new threads but Sandy Hood warns in
  his book that he has trouble with W98. I might add that
  Sandy's demos passed dynamic references - which is quite
  naughty, so I expect he would have trouble. If he followed
  the examples in the VO White Paper on multi-threading he
  should probably have created static memory space first and
  then passed the objects to the thread. Anyway, I have been
  creating threads which pop up warning and message boxes
  successfully in all versions of windows (so far - touch
  wood!) so I assume its OK if handled carefully.
The function you referenced seems only to be used in
  AScan(), or at least I can't find it elsewhere, but the
  code is not provided. Take a look also at __WCGCStart()
  and __WCGCEnd(), for which the VO is provided (in the
  Application class). Again, nothing in the SDK calls these

  functions but they are there??? CreateCGDump() is about
  the only window into what is happening.
This is one of the topics we are going to question Sabo over
  at DevCon 2000 Australia.

Geoff


From jpm@isassoc.com Sat Mar 18 01:06:43 2000

Geoff,

This is of interest to me since I need to start working on
  some multithreaded solutions in the near future... Doesn't
  VO 2.5 come with a multithreaded standard app under
  samples where each DBF you open spawns a new thread for
  the standard datawindow?  That uses the GUI and it's one
  of the samples bundled in with 2.5 -- has anyone had
  problems using the GUI in threads?

Regards,
John


From mike@richsoftware.com Sat Mar 18 02:28:52 2000

Geoff,

>
explicitly, I take this to be thread specific. I say this
  because each thread is given its own dynamic memory space.
<
That's pretty much what they said they were going to do at
  the '97 technicon.
>
dynamic memory data in the calling thread. I also assume
  that each thread is also given its own static memory (ie
  heap) space.
<
I'm not sure about that: the reason why they wanted to
  create separate dynamic memory spaces for each thread was
  so that the Garbage Collector didn't run in one thread and
  move something that was being concurrently manipulated in
  another thread. That wouldn't be the case with static
  memory.
The concern I have is that with the above approach, it still
  might not be safe to use objects created in one thread in
  another thread.

Mike


From geoffsch@bigpond.net.au Sat Mar 18 12:12:17 2000

Mike,

Your suspicion is correct about static memory. I just re-
  read the CA white paper on multithreading and it clearly
  states that all threads created by the same process share
  the same static memory space. Its only dynamic memory

  which is created to be thread-independent. But this
  wouldn't matter anyway because of the nature of dynamic
  memory. It is simply moved and removed as needed so thread
  origin is quite irrelevant, as long as the GC is capable
  of finding ANY reference, no matter the thread of origin.
  This is what I assume they mean by "thread safe".
I also assume that the GC runs in its own thread. (Any CA
  people can feel free to jump in at this point - Uwe???.)
However, all that seems fine and now I am more suspicious of
  Sandy Hood's demos in his new book. The CA white paper
  goes to some trouble to put the passed data into static
  memory so it is obviously important. Sandy doesn't and
  acknowledges problems. The trick simply appears to be to
  guarantee the scope of the object passed to the thread so
  that the originating thread does not destory (or GC move)
  it before the thread is finished with it. VO classes
  should be safe from moving because RegisterKid() updates
  pointers accordingly. Then the remaining issue is to
  prevent the destruction of an object being used in a
  thread - in which case mutexes, semaphores or system atoms
  can come to the rescue.

Geoff


From 100725.3150@compuserve.com Sun Mar 19 01:39:10 2000

Geoff,

pmfji, i have no deeper knowlegde neither of Threads nor the
  GC functionality, but:
>
VOclasses should be safe from moving because RegisterKid()
  updates pointers accordingly. Then the remaining issue is
  to prevent the destruction of an object being used in a
  thread
<
I understood that the GC "normally" uses counters to decide
  if an entity still is referenced by somebody, so
  preventing it from being killed. If so, and if the
  RegisterKid more or less does provide the same
  functionality over threadborders, i wouldn't see why the
  GC shouldn't "know" about the "not yet kill" here. So
  destruction shouldn't be a task to bother _us_. Maybe the
  probs start when working with selfcreated Winresources??
just my 2 cent (training for the Euro ;-) )

Karl


From geoffsch@bigpond.net.au Sun Mar 19 09:30:51 2000

Hi Karl,

We are talking about slightly different things. I was really
  discussing more about the "moving" aspect, not the "kill"
  decision. The GC does not "kill" anything, it only moves.
  The VO code (which you can track through the SDK) shows
  this counting incrementing and decrementing and obviously
  an object is given a null pointer once its reference count

  goes to zero. But you could easily assign a null pointer
  (or null srtring) yourself and thus the object will be
  ignored by the GC  (ie "killed" <g>).
No, the discussion was more about the "moving" aspect.
  RegisterKid() places a reference to a pointer (ie to your
  dynamic object) into a global array and stores the pointer
  onto the Heap with GlobalAlloc(). The Heap is safe from
  everything because we are now in a windows resource -
  something which VO must now manage. When the GC has done
  its thing and moved the object it simply updates the
  pointer in the array (which is in turned, stored on the
  Heap). For a more thorough 'explanation' of this you
  should look at the SDK code for RegisterKid(),
  UnRegisterKid() and some of the enabling functions like
  __WCRegisterXXX() and related functions.
But the "kill" issue is important because I am trying to
  understand in which bit of memory space are these Windows
  resources created. When I create a brush, where is it
  created? As I said earlier, VO is full of these
  inconsistencies with Windows "rules" in that it routinely
  creates brushes and other objects and does NOT destroy
  them. Are these the possible causes of the ultimate and
  inexplicable crashes after an app runs for three weeks?
I would like CA to come clean on a number of these issues -
  we as developers may be blaming ourselves for issues that
  are really the fault of the Dev Team.

Geoff


From mike@richsoftware.com Sun Mar 19 05:00:04 2000

Geoff,

>
I also assume that the GC runs in its own thread.
<
I stand to be corrected, but I doubt that. Garbage
  collection is triggered by operations which require
  allocation of dynamic memory (or by calling the Collect
  functions). The operation which triggers garbage
  collection can't proceed until collection has taken place
  (firstly, because it probably needs the collected memory,
  and secondly because you wouldn't want your thread
  pootling on blithely while all its references are being
  reassigned in the background).
My understanding was that the reason why each thread was
  given a separate dynamic heap was so that the when the GC
  kicks in within a thread it only operates on the dynamic
  memory for that thread. I also suspect the Enter/
  LeaveCGCSection functions are to block the garbage
  collector from running in separate threads concurrently.
Incidentally, the CA white paper on multithreading you
  mention: is this in SDT? If so, we need to get a new
  subscription. So far the only articles I've read are in
  the "How To..." section of the help (which originally
  dates back to 2.0) and Ginny's 99 Technicon paper.

Mike


From geoffsch@bigpond.net.au Sun Mar 19 09:16:56 2000

Hi Mike,

>
I stand to be corrected, but I doubt that. Garbage
  collection is triggered by operations which require...
<
You may be right - although using critical sections the GC
  could still block other threads. But I have my doubts. To
  me it wouldn't matter because you only move one object at
  a time and then reset the pointer. This would not affect
  an operating app at all. Well, I guess VO uses
  GlobalAlloc() to store these pointers on the Heap and thus
  they are safe from everything, so it wouldn't matter to
  the app that it was "suddenly" moved. They are all just
  referencing this pointer in the heap and using offests
  from there. I can't imagine the GC not being in a thread -
  what if you had to re-order 16MB of memory! Maybe it is
  that fast. Maybe someone can answer this definitively?
>
The operation which triggers garbage collection can't
  proceed until collection has taken place (firstly, because
  it probably needs the collected memory
<
Not at all. There is plenty of static memory (Heap) at this
  point - it is independent of dynamic memory.
>
and secondly because you wouldn't want your thread pootling
  on blithely while all its references are being reassigned
  in the background).
<
See above. I don't think this is a problem at all.
>
My understanding was that the reason why each thread was
  given a separate dynamic heap was so that the when the GC
  kicks in within a thread it only operates on the dynamic
  memory for that thread. I also suspect the Enter/
  LeaveCGCSection functions are to block the garbage
  collector from running in separate threads concurrently.
<
I agree with this. And it would be nice to know, save that
  function is only ever used in AScan(). What's so special
  about arrays that doesn't apply to other dynamic objects?
>
Incidentally, the CA white paper on multithreading you
  mention: is this in SDT? If so, we need to get a new
  subscription.
<
No, its in the on-line help section (ie on the CD). There
  are several excellent white papers there that are really
  mandatory reading. I can't imagine why they were "buried'
  so well <g>. When CA made the new pdf manuals they should
  have included these files as well. But did you see Uwe's
  article in 3/99 of SDT. This is by far the most detailed
  technical reference to the GC that has been published.

Geoff


From mike@richsoftware.com Mon Mar 20 21:42:10 2000

Geoff,

>
Not at all. There is plenty of static memory (Heap) at this
  point - it is independent of dynamic memory.
<
What I was saying was: suppose your app tries to instantiate
  an object, create an array or something like that, and the
  dynamic memory manager doesn't have a free block large
  enough to do what you want. So it has two choices: either
  it can extend the size of the dynamic memory pool, or it
  can perform garbage collection to defragment the pool.

Mike


From geoffsch@bigpond.net.au Tue Mar 21 11:53:58 2000

...or the third option. That it can't do either and crashes.
  <g>
But I still don't see that as being a problem.
I also assume that once the GC "starts", it does all dyn
  memory and doesn't just stop for the sake of one
  reference.

Geoff


From gcaughey@compuserve.com Mon Mar 20 23:20:17 2000

Geoff,

The recommendation to not use GUI in worker threads comes
  from Microsoft.
Sure, you can do it (and I have for demo purposes for the
  sessions I've given on multithreading at CA-World and in
  Germany), but you really shouldn't design a production app
  like that. I'll be doing a 2-part session on
  multithreading at CA-World this year, so I hope everyone
  interested in this topic will attend.

Ginny


From jpm@isassoc.com Mon Mar 20 23:41:24 2000

Ginny,

I'm curious for the reason not to do something like this...
  are there potential stability problems?  To me it would
  seem very handy to open datawindows in different threads.
  That way you could open a datawindow, start a lengthy
  process and still be able to do other work with the app.

TIA,
John


From gcaughey@compuserve.com Tue Mar 21 00:25:00 2000

John,

I can only guess at some of the technical reasons for
  Microsoft's recommendation. Historically, the thread
  support in Windows came from OS/2, which never supported
  GUI except in the main thread. So Microsoft never planned
  for GUI support for multithreading and AFAIK the GDI
  subsystem itself is not thread safe. (Definitely MFC is
  not.)
But your question is really one of practicality. If you have
  datawindows running on separate threads, what is the
  actual *advantage* of the multithreading vs. using
  multitasking instead (i.e., running separate applets for
  each datawindow or using OLE automation)? The shared
  resources (globals, statics) that can make multithreading
  a good thing can also make multithreaded apps hard to
  write correctly. And running threads does incur some
  overhead at the OS level managing all the threads.
And anyway, what you're hoping to accomplish in your example
  is to run some lengthy process in the background, and that
  part probably isn't the GUI part. For example, if the
  lengthy process involves a long update, you could spin
  that part off into a worker thread. I have a production
  app that spins off worker threads to poll several serial
  ports and write out info to a file if things happen on the
  ports - definitely a lengthy process because it just keeps
  running until somebody hits the Cancel button on the
  modeless dialog window. But the dialog and the polling
  happen on different threads. The worker threads use
  PostMessage to update stuff on the GUI status bar, and the
  GUI uses PostThreadMessage to send information to each of
  the worker threads that they may need, but the workers
  never manipulate the GUI directly. Meanwhile, you can
  still do stuff on the main thread (the GUI part) while the
  worker threads do their work.

HTH,
Ginny


From jpm@isassoc.com Tue Mar 21 01:15:17 2000

Ginny,

Hmmm... I'm just starting my move to 2.5 so I haven't done
  any thread work yet but had imagined using the GUI to
  provide feedback on lengthy processes... I hadn't thought
  of PostMessage/PostThreadMessage to handle that via a
  modeless dialog.  I'll have to give this some more
  thought, thanks for the tip.

Regards,
John


From geoffsch@bigpond.net.au Tue Mar 21 12:08:09 2000

Ginny and John,

Perhaps the MS warning is slightly overstated. As I
  understand it, the warning related to the possibility of
  one thread destroying an object which another thread is
  painting or using. But this only involves GDI objects:
  pens, brushes, fonts, bitmaps, regions and palettes. The
  advice (and I believe Petzold echoes this) was to either
  not share GDI objects (ie each thread creates its own) or
  to use critical sections. Petzold offers examples of GUI
  working quite successfully within secondary threads but he
  certainly adheres to the above warning.
Sandy Hood also demonstrates a perfectly working example
  (except for W98 <g>, apparently...) where a dynamic object
  is passed to the thread for use.
Although I personally would prefer to see him pass the
  pointer a different way, it does work.
Beyond this (and other issues of thread sychnonisation), I
  can't see any problems with GUI in secondary threads.

Geoff


From gcaughey@compuserve.com Wed Mar 22 00:24:35 2000

Geoff,

I don't think Microsoft's warning is at all overstated.
  Unless you're writing code using just API calls and no
  foundation classes written by somebody else, you can't
  really understand all the potential places for race
  condition problems. Even if Petzold is correct that
  Windows 98 apparently correctly serializes access to
  graphics drawing functions except for the problem with GDI
  objects, what about NT and Windows 2000? And what are you
  gaining anyway? Is there no other way to accomplish your
  goal? If you want to write your own thread-safe foundation
  classes, please don't let me dissuade you, but you might
  want to check with Larry Atkins to get a idea how much
  work might be involved. <g>

Ginny


From geoffsch@bigpond.net.au Wed Mar 22 06:57:17 2000

Ginny,

>
Is there no other way to accomplish your goal?
<
Yes, sure. But often you want to know that a thread is
  "finished" or have something to simply report progress.
  I'm not advocating writing a complex app within - you are
  right, it would seem counter productive. But I am
  suggesting that a GUI class instantiated within the
  thread, used in the thread and destroyed within the thread
  should have absolutely no fear from anything. And I see
  nothing in MS or CA literature to suggest otherwise.
That's all. Personally, I would only ever advocate

  asynchronous activities for threads so that race
  conditions are minimised and in truth, I would often
  prefer to launch another process rather than a thread to
  control some things. But, sometimes, it is a powerful
  attraction to be able to share memory to a thread process.
>
If you want to write your own thread-safe foundation
  classes, please don't let me dissuade you, but you might
  want to check with Larry Atkins to get a idea how much
  work might be involved. <g>
<
No way <bg>.

Geoff


From gcaughey@compuserve.com Wed Mar 22 08:40:44 2000

Geoff,

The easy and very safe way to update your GUI from your
  thread is to just use PostMessage from the thread to the
  GUI.  You may be right that it's not a problem
  instantiating a window within a worker thread assuming
  that you can ensure that it will always be destroyed while
  the thread is active, etc., but where is the advantage in
  doing so? I don't know about you, but I tend to find
  enough unpleasant surprises even when I do follow vendors'
  advice. <g>

Ginny


From geoffsch@bigpond.net.au Wed Mar 22 21:04:51 2000

Ginny,

So what you are saying is the you don't want to even risk
  the main thread terminating the thread without that thread
  being offered the courtesy of destroying its own objects?
  Well given they are all dynamic objects, it shouldn't
  matter. I think once you start controlliong GUI by sending
  messages all round the place I think things are getting
  just a little too complicated for my liking. the code has
  to be readable and supportable. I hardly see an issue with
  api calls to MessageBox() etc, nor regular GUI anyway.
But it doesn't matter that the main thread closes the sub-
  thread. As everything that matters is in dynamic memory
  its a simple issue that the GC will clean things up in due
  course anyway. If that thread creates its own objects in
  static memory then I think that's certainly dangerous but
  to me, this would be the biggest no-no if there is an
  issue that the main can and might terminate the suib-
  thread.
By the way, I have not been able to find negative references
  from MS regarding the use of GUI in sub-threads. Would you
  mind pointing me to a web page or two that discusses this?
  The only material I have found was written by Charles
  Petzold and he is quite happy at using GUI in threads.

Thanks.
Geoff


From gstark@DONT_SPAM_RedbacksWeb.com Thu Mar 23 08:13:40
  2000

Geoff,

>
So what you are saying is the you don't want to even risk
  the main thread terminating the thread without that thread
  being offered the courtesy of destroying its own objects?
  Well given they are all dynamic objects, it
<
I'm not reading that into what Ginny is saying at all.
What I am seeing that she's saying is that any GUI interface
  that you present to your user is donw so through the
  application's main thread, and that if you want to update
  a GUI element with, say, progress information, your
  spawned thread posts a message to the queue for the main
  thread to act upon.
>
shouldn't matter. I think once you start controlliong GUI by
  sending messages all round the place I think things are
  getting just a little too
<
While yes, this is complex, how is it any different from
  anything else that we do in our Windoze apps? For
  instance, we might have a browser and a couple of data
  windws open, we update a data record and the browser
  updates itself as a result.
Or am I missing something here?

Gary Stark


From geoffsch@bigpond.net.au Thu Mar 23 08:47:01 2000

Gary,

OK - I'll put my case as succinctly as possible.
(1)    Yes - I agree with everyone, avoid GUI if possible.
  Especially if you are trying to pass objects into the new
  thread. It does work - and work quite well. But the issues
  of scope and availability are very real and need to be
  understood. But this does NOT invalidate the principle. It
  only urges care.
(2)    If Rule 1 has to be broken, do so with dynamic
  objects created completely within the new thread only. Set
  up parameters to be passed in static memory using
  carefully designed structures. And never modify static
  memory unless you really know all the conditions that
  might lead to its later use.
I have a number of simple apps (ahead of building a server
  app) and they work quite comfortably on W2K, NT4 and W98.
  I am not interested in W95 and no longer offer that
  support to my clients. To me, posting messages out of a
  sub-thread to the master does not solve any of the "race"
  conditions spoken of, creates a few extra problems of its

  own and really does make things complex and difficult to
  debug. I say again, I cannot find all these "warnings"
  regarding GUI in multi-threaded apps (at least from an MS
  perspective) but I have found quite a few multi-threaded
  demo apps which also work quite successfully. I am quite
  happy to use multi-threading.

Geoff


From squinn@brutecom.com.au Thu Mar 23 09:10:50 2000

Geoff

You might like to browse a book called
Programming Applications for Microsoft Windows - Fourth
  Edition
    Jeffery Richter
    MSPress
    ISBN 1-57231-996-8
10 or so chapters (350+ pages) on threads alone, lots more
  info than Petzold gives in his book (1 chapter of 34-35
  pages).
It landed on my doorstep this morning, so I haven't read it
  cover to cover yet<g>, only part of chapter 6 (Thread
  Basics) so far.
The latest Petzold landed on my doorstep this morning as
  well<g>.

HTH
Steve Quinn


From geoffsch@bigpond.net.au Thu Mar 23 14:00:41 2000

Steve,

Please offer a quick review when you have had time to read
  it.

Thanks.
Geoff


From gcaughey@compuserve.com Thu Mar 23 23:39:29 2000

Steve,

Another great source of info on multithreading is
  _Multithreading Applications in Win32_ by Beveridge and
  Wiener (Addison-Wesley ISBN 0-201-44234-5). It isn't a new
  book (copyright 1997) but it's the best I've found so far.
  But I'll also look for the Richter book - sounds
  interesting.

Ginny


From gstark@DONT_SPAM_RedbacksWeb.com Fri Mar 24 02:39:13
  2000


Geoff,

>
OK - I'll put my case as succinctly as possible.
(1)    Yes - I agree with everyone, avoid GUI if possible.
  Especially if you
<
But why should you even _need_ to create a GUI object within
  your spawned thread? are trying to pass objects into the
  new thread. It does work - and work
>
quite well. But the issues of scope and availability are
  very real and need to be understood. But this does NOT
  invalidate the principle. It only urges
<
Yes these issues are real, but I still don't see your point.
>
I have a number of simple apps (ahead of building a server
  app) and they work quite comfortably on W2K, NT4 and W98.
  I am not interested in W95 and
<
Er, what's the actual product name when you look up Win98?
  <g>
>
no longer offer that support to my clients. To me, posting
  messages out of a sub-thread to the master does not solve
  any of the "race" conditions spoken of, creates a few
  extra problems of its own and really does make things
<
But this happens by default, because you're writing programs
  for use within a Windoze environment. Wanna do something ?
  There will be a message posted somewhere in the Windoze
  message queue.
>
complex and difficult to debug. I say again, I cannot find
  all these
<
Windoze apps are complex and difficult to debug. That, I'm
  afraid, is the nature of the beast.

Gary Stark


From geoffsch@bigpond.net.au Fri Mar 24 19:10:28 2000

Gary,

I guess it boils down to an issue of convenience and
  simplicity. Its just that I and others have found certain
  circumstances of GUI use in threads that do not appear to
  cause problems. And if you think that was the most pre-
  qualified remark in history, you are probably right <g>.
In all seriousness, we have all been thoroughly warned but I
  don't want to see those warnings overplayed. All I know is
  that the circumstances we have developed are quite OK.
  Happy to show you a couple at Devcon.

Geoff


From gcaughey@compuserve.com Thu Mar 23 23:48:44 2000

Gary,

That's pretty much it. "Sending messages all around the
  place" is the way Windows works, and that's also what
  happens when you use a foundation class to hide this
  behavior from you - it's still a WM_SETTEXT message for a
  control or SB_SETTEXT message for a status bar. Windows is
  optimised for speed for delivering Windows messages, and
  they are delivered in a thread-safe manner: messages are
  always received by a window on the same thread that
  created the window.

Ginny


From gcaughey@compuserve.com Fri Mar 24 02:23:09 2000

Gary,

That's about it. "Sending messages all round the place" is
  exactly how Windows works. Even if you're using foundation
  classes to hide this stuff from you, you're still sending
  WM_SETTEXT or SB_SETTEXT messages to update the text in a
  control or status bar. Windows is designed for fast
  messaging, and posting messages is thread safe: messages
  are always delivered to a window on the same thread that
  the window was created on.

Ginny


From gcaughey@compuserve.com Mon Mar 20 23:16:31 2000

Mike,

I don't know the answer to your specific question, but I
  think your assumption is correct. CA says the GC is now
  thread safe as of VO 2.5. (VO 2.5a fixed some additional
  things in the RDDs regarding threading.)
As a practical matter I think it's probably safest to treat
  the whole GC as a black box and not try to figure out its
  internal workings. After all, CA could change the
  implementation at some point. Is there a particular reason
  you need to know? Uwe Holz at CA has been very forthcoming
  with information (for example in the SDT article), but
  some aspects of the GC are considered CA trade secrets I
  believe.

Ginny


From mike@richsoftware.com Tue Mar 21 00:12:31 2000

Ginny,

Well apart from simple curiosity, I have a lingering
  paranoia about multithreading, specifically what happens

  when you pass an object created in one thread into
  another. I suppose I'll have to read the SDT article to
  set my mind to rest.

Mike


From geoffsch@bigpond.net.au Tue Mar 21 12:19:16 2000

Ginny,

Whilst I probably agree with your 'blackbox" philosophy, a
  problem arises with this trade secret approach.
What do we do when something does not work properly?
Yes, we can (and do) report issues through to development
  but in the mean time a solution or workaround has to be
  found. In any event, development sometimes have reasons
  for not "fixing" implied bugs so therefor a better
  understanding of the circumstances leading to the
  situation will help me, as a software developer, find my
  own solutions. I have two simple examples. I have
  circumstances where InCollect() itself causes a GPF. This
  is repeatable. It is not supposed to. Sabo proudly
  announces VO is now threadsafe but you mustn't use it for
  GUI (and refuses to elaborate). What about
  _VOLoadLibrary()? Its undocumented but everyone (except
  VO) seem to use it. Why? What is it? What makes it
  different from LoadLibrary()? Why the preference to use it
  when CA does not and it is not documented? Why is that
  _VOFreeLibrary() will often remove GPF's caused by using
  FreeLibrary(). Its undocumented also, widely used and
  totally ignored by CA in writing VO.
As Mike said, I too am simply interested. I want to write
  better apps and make them more stable. An understanding of
  some issues where documentaion is still particularly poor
  is all I am seeking. I don't plan to give up that pursuit
  <g>.

Geoff


From gcaughey@compuserve.com Tue Mar 21 23:50:41 2000

Geoff,

You do raise an important issue: what do you do if something
  doesn't work and the vendor of the tool you're using
  doesn't give you enough inside information to fix the
  problem? Those of us who have worked with VO (and for that
  matter, Windows) for a number of years have all been in
  that situation.
Here are the choices as far as I can tell:
1. Follow the recommended practices of the people who wrote
  the tools you use. For example, why would you want to
  disregard Microsoft's and CA's advice not to use GUI
  elements in worker threads? Masochism? Microsoft KNOWS
  that the MFC are not thread safe, and similarly CA KNOWS
  that the GUI Classes are not. Both groups of developers
  have experience writing code that is thread safe so they
  understand the work involved. Neither company has any

  interest in fixing the multihreaded GUI problem for you so
  they tell you not to do it.
2. Don't use a feature you have found doesn't work. If
  InCollect() fails on you in some situation, don't use it
  in that situation! Find some other way to get your app to
  do what you want.
3. Keep experimenting until you find something that does
  work. I did this with VO 2.5 with the Dynsize(40)
  workaround. The downside is, you never know if what you're
  doing is really a fix, or if it just moves the problem
  somewhere else. But as long as your apps work, you can
  take the pragmatic approach and go with it.
3. Report the bug to the vendor and hope for a quick fix. I
  have done this many times, and in every case where I was
  able to provide CA with a small reproducible test case, CA
  addressed the problem quickly. In one case the CA
  developer and I agreed not to pursue a particular problem
  since I had already moved my app to ClassMate and no
  longer had the problem, but the CA response was still
  quick and appropriate. If you can reproduce the InCollect
  GPF in a small test case, I'll bet CA would be very happy
  to address that problem.
4. Use a different tool. But unless you believe that some
  new tool is going to be perfect, you're eventually going
  to end up right back at square one.

Ginny


From geoffsch@bigpond.net.au Wed Mar 22 07:11:42 2000

Ginny,

I guess in practice I follow both your paragraph 3 options.
Somehow I have trouble with (1) because its like building a
  huge new dam to resolve a water shortage but then telling
  the people not to drink it because you can't guarantee
  water quality :((. So I guess that this tells me that CA
  and MS must be human after all? Certainly (4) is no option
  <g>.
But (2) is not an option. Something like InCollect() is a
  primary function.
There has never been any warnings about it and it is
  provided precisely for quality control so I think it is
  worthy of public comment.
The trouble with (3) (second para) is that our usual sources
  of support no longer exist. Where once I too could just
  send some sample code off to Marijo, this is no longer
  possible. Oh yes, I have a site number and everything but
  way out here in Australia it is a problem. I can lodge a
  support call through the CA office in Sydney (all ready a
  long distance call) but Sydney acknowledge that they
  cannot deal with the problem and thus refer you on to
  experts in the US. Well now I am up to an international
  call. There is a part in this that email can play but this
  method is not the entry into the system. And there is the
  time differential just to make things awkward. Quick - no.
  Expensive - yes. Time consuming - yes.
So, I would like to keep raising issues here and at
  conferences until either CA get frustrated enough to make

  at least some consessionary statement or your (3) (first
  para) yields something of benefit to all.

Geoff


From gcaughey@compuserve.com Wed Mar 22 09:02:31 2000

Geoff,

I wasn't aware that CA was no longer interested in seeing
  small reproducible samples of bugs. But maybe you can't
  get your problem to reproduce itself in a small sample. I
  certainly had that problem with the 5333 error 50s I got
  when I first moved to VO 2.5, but fortunately somebody
  else was able to come up with a reasonable test case and
  CA was able to fix the problem for 2.5a.
I have to ask, does Dynsize(40) make the InCollect problem
  go away?

Ginny


From geoffsch@bigpond.net.au Wed Mar 22 21:09:14 2000

Ginny,

Unfortunately it is official policy. Marijo has written to
  me. It is just as official that development staff cannot
  raise or comment on issues in the Open Forum.
>
I have to ask, does Dynsize(40) make the InCollect problem
  go away?
<
No - I use this routinely anyway. These two things are
  unrelated.

Geoff