I have a bug. In WinForm .NET2.0 application my HeavyFunction can be called from mouse click event handlers. So, When I'm starting fast clicking I have crash on file writing because of HeavyFunction entered second time.
My solution. I remembered the things relative to APC and decided to synchronize the things fairly. I.e. I want to exclude APC effects in the HeavyFunction. So, I used ThreadPool. For synchronization I tried to use SyncLock (Visual Basic). And failed. Mutexes don't work either. I simply cannot understand how my HeavyFunction can be called from the same thread twice at a time. But it does. I thought that if I use ThreadPool then I force every call be executed on different thread.
The definition of APC http://msdn.microsoft.com/en-us/library/ms681951%28v=vs.85%29.aspx.
Here is "Thread Synchronization Fairness in the CLR" by Jeffrey Richter (makes me sick):
http://codeguru.earthweb.com/csharp/.net/net_general/threads/article.php/c4647/Thread-Synchronization-Fairness-in-the-CLR.htm
EDIT: It seems that I found the reason of crash exception. It's antivirus AVG. Probably he considers suspicious activity when somebody clicks very fast and it causes fast file open/write operations. Or it slows down my PC so much. Anyway I cannot reproduce crash when AVG disabled. Although ProcMon shows that AVG access the file while enabled.
Finally, can somebody explain APC to me? Namely, can APC lead to double enter to the same function in the same thread?
I understood that it can from this text:
"An asynchronous procedure call (APC) is a function that executes asynchronously in the context of a particular thread. When an APC is queued to a thread, the system issues a software interrupt. The next time the thread is scheduled, it will run the APC function. "
I'm afraid to die without this understanding.
You're seeing this behavior because Win32 messages are implicitly reentrant. This is particularly true in .NET because the runtime may pump on your behalf whenever your UI thread blocks.
The normal way to work around this behavior is to either disable the controls while the long-running event handler is executing, or keep a queue of actions to run instead of kicking off another handler each time.
APCs are a red herring. They can "borrow" a thread in an alertable wait (which the .NET runtime usually uses for blocked UI threads), but an APC will not invoke a UI event handler (at least, I cannot think of any situation that would cause this).