Re: Problems with Threading and CDO in C# Winforms app

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



I am definitely starting the threads as STA

I have gone through the method launched in a thread, and the functions that
it calls and have verified that I am cleaning up the COM objects that I
instantiate, either explicitly, or by the variables going out of scope.

I have added a call to WaitForPendingFinalizers at the end of my thread
method, and have retested, however it seems to make no difference.

I tried adding a call to WaitForPendingFinalizers in my btnExit function and
when execution reaches this call, my app stops here and never goes beyond
this call. TaskManager shows the app taking some small slices of CPU now and
again, usuually within a couple of minutes I get a COM Exception for a
thread deadlock.

I'm intrigued by your suggestion that 3 threads should be able to handle
this, and would like to know more about what you had in mind.

If I divide the work (150 mailboxes) by 3 threads, each thread would have to
process 50 mailboxes. If this is done in a serial manner, I expect the
elapsed runtime would be at least 20 minutes. Is there another way to have
50 MAPI sessions going in a single thread, so I can complete the work with
an elapsed time of 5 minutes or less that the app enjoys now with 150
threads?

Thanks in advance for any suggestions you might have.

Steve




"Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx> wrote in message
news:eajEogQTGHA.5108@xxxxxxxxxxxxxxxxxxxxxxx
Well, the CDO library (CDO 1.2.1) is a client side COM automation library,
that means it is designed to be used from a Windows client style
application, not from a multi-threaded server style application. The CDO
library uses 'apartment' threaded objects, that means their instances must
and will run in an STA thread. The only STA thread in a windows
application
(by default) is the UI thread, so, if you create CDO object instances from
auxiliary threads in your application, and you don't initialize these
threads to enter a STA, your COM objects will run in the UI thread and
your
call will have to be marshaled.
That means that in your case you have 150 threads that do nothing else
than
waiting for their calls to be serialized to the one and only STA (UI)
thread, I would not call this very inefficient. But there is more, you
have
to make sure that the UI thread survives the other threads and that it
survives the finalizer thread. This is needed because the finalizer thread
will have to 'finalize' the RCW's whenever you are releasing the COM
object
references. Now the question is, how do you release the object references?
Is this done before the thread procedure returns, or are you simply
relying
on the finalizer to clean-up? If it's the latter, you are in trouble, the
finalizer thread will most certainly be unable to release all the RCW's
because the STA will be torn down before or while your finalizers run. The
only option you have to solve this is:
- restrict the number of threads (say 2 or 3, more makes no sense,
really),
- initialize them as STA threads,
- make sure you release the COM objects and pump the message queue (by
calling WaitForPendingFinalizers) before returning from your thread
procedures, and
- make sure no exceptions in your thread procedures can go unhandled.

Willy.





"Steve Smith" <steve.a.smith@xxxxxxx> wrote in message
news:eP6LWUPTGHA.1572@xxxxxxxxxxxxxxxxxxxxxxx
|I did include the following code when launching the threads at one time,
but
| have since commented it out to see if it was part of the problem.
|
| y.theThread.SetApartmentState(ApartmentState.STA);
|
| There is no contest here, just trying to get the job done in the most
| efficient manner. The appilcation seems to work quite well. What use to
take
| 45 minutes is now complete in less than 10 minutes, the only remaining
| problem is the Application.Exit() issue I have described.
|
| The old single-threaded VB6 application takes close to 45 minutes to
| complete. Some of the CDO calls are very expensive, particularly the
mailbox
| Logon, so I expected that executing those calls once instead of 2 or
more
| times would be an improvement.
|
| This application is run on a dedicated, well-equipped workstation, after
| system changes have been made to a large Exchange environment. It's
purpose
| is to confirm that each mailbox store on each server has mail flowing
| between each store, as well as to and from external mail systems. It
also
| confirms access to Public Folders, and verifies that the virus
detection
| and notification systems are working.
|
| Thanks for the feedback.
|
| Steve
|
|
| "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx> wrote in message
| news:un$CV0HTGHA.6084@xxxxxxxxxxxxxxxxxxxxxxx
| >
| > Are you sure all of your threads have entered the STA? This is
required
by
| > CDO.
| > Note that I see no reason at all to have 150 threads, and all
reporting
| > back
| > to the UI thread, is this part of a contest or what? You are just
wasting
| > 150MB of memory for the thread stacks and you waste a lot of CPU
resources
| > just to switch the threads which will just slow down the whole
| > application.
| >
| >
| > Willy.
| >
| > "Steve Smith" <steve.a.smith@xxxxxxx> wrote in message
| > news:uItCN2ETGHA.1608@xxxxxxxxxxxxxxxxxxxxxxx
| > |I have written a winforms application that launches approximately 150
| > | threads with
| > | Thread.ThreadStart()
| > |
| > | Each thread uses CDO 1.21 to logon to a different Exchange mailbox
and
| > | send/receive a number of mail messages, reporting back to the UI
thread
| > | through the use of a Queue object. When all messages that are
expected
| > have
| > | been received, each thread sends a final update to the UI and the
method
| > | should exit, which should terminate the thread.
| > |
| > | Everything works well for the most part, although I am doing battle
with
| > the
| > | Outlook Security dialog on some mailboxes.
| > |
| > | When all threads have completed their work, the Exit button on the
UI
is
| > | enabled. When I click it, the Application.Exit() function is called,
and
| > the
| > | UI disappears, but the application continues to run. In the debug
| > | environment eventually I get a thread deadlock message. At this
point,
| > there
| > | should only be one thread running.
| > |
| > | I have read numerous articles on threading and examined many samples
and
| > | cannot see anything wrong with the way I have coded this
application.
| > |
| > | If anyone has experienced this type of problem, or has a suggestion
on
| > how
| > I
| > | could try to nail this down, I would appreciate it. Is it possible
the
| > CDO
| > | object is part of the problem?
| > |
| > | Thanks in advance
| > |
| > | Steve
| > |
| > |
| > |
| > |
| >
| >
|
|




.


Quantcast