CoWaitForMultipleHandles

joe_pool_is

Well-known member
Joined
Jan 18, 2004
Messages
451
Location
Texas
I got this message today while debugging through a very small program using Visual Studio 2005 Express with my C# program:

ContextSwitchDeadlock was detected Message:
The CLR has been unable to transition from COM context 0x1b11b8 to COM context 0x1b1328 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
Is this something that I could have caused in my simple application? (All it does is fools around with registry settings, learning how to use different tools like the commonDialog in C# 2005, etc.) I was stepping over this piece of code when the debugger froze.
Code:
// String folder
// = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
private void RegistryWork(bool bIn) {
  String program = System.IO.Path.GetFileNameWithoutExtension(Application.ExecutablePath);

  try { // HKEY_CURRENT_USER\Software\poojo.com\program

    Microsoft.Win32.RegistryKey rkSoftware; 

    rkSoftware = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("Software");

    Microsoft.Win32.RegistryKey rkCompany = rkSoftware.CreateSubKey("poojo.com");

    Microsoft.Win32.RegistryKey rkProgram = rkCompany.CreateSubKey(program);

    if (bIn == true) {

      rkProgram.GetValue("Folder", folder);

    } else {

      rkProgram.SetValue("Folder", folder, Microsoft.Win32.RegistryValueKind.String);

    }

  } catch (Exception ex) {

    MessageBox.Show("Unable to use registry.\n" + ex.Message, "Registry", MessageBoxButtons.OK);

  }

}
It froze on the statement
Code:
if (bIn == true)
Why? Did I do something, or was this something caused by some other Microsoft thing running in the background?



This has only happened once; I have not been able to reproduce it.
 
dynamic_sysop said:
you are trying to create the subkey Software under CurrentUser ...

the registry already has a subkey called Software which wont help much with your crashes :)
Really? It was my understanding that CreateSubKey() only created the key if it did not exist. Is there a preferred technique I should be using?
 
You are correct. CreateSubKey opens the key for write access if it already exists.

And if you are only using managed code and you arent multithreading then I dont see how this could be caused by you. Is this reproducable or has it only happened once?
 
Really really really weird question: does the your app have the STAThread attribute set somewhere (usually near the Main method)? If so, and if the bug is reproducable, try replacing it with MTAThread.

That errors sounds familiar to COM single threaded appartment problems where one thread tries to access a COM object (only allowed on the correct thread) but the thread that is allowed to use the COM object is blocking.

Off course finding out & fixing the block would also help ;).
 
So far, the error has only occurred the one time, but I havent done extensive debugging on it. It is in managed C# code. If there is a preferred method of reading/writing registry keys, Id certainly like to know.

Id like to be able to test for the keys on load and on create. For OnLoad:
1. create a key and initialize it.
2. if key exists (not null),
3. read values
4. else
5. set defaults
6. delete the key (well, that would be for "unmanaged code" like c++)

For OnClose
1. create a key and initialize it.
2. try
3. write values
4. catch and throw away any errors
5. delete the key for "unmanaged code"

But I want to make sure I have something robust that isnt going to create a bug that is going to terrorize or harass me.

Here is what I am using in C#:
Code:
[color=#0000ff]private [/color][color=#0000ff]void[/color] RegistryWork([color=#0000ff]bool[/color] bIn) {
[color=#0000ff]try[/color] { [color=#008000]// HKEY_CURRENT_USER\Software\poojo.com\program[/color]
Microsoft.Win32.[color=#008080]RegistryKey[/color] rkSoftware;
rkSoftware = Microsoft.Win32.[color=#008080]Registry[/color].CurrentUser.CreateSubKey([color=#800000]"Software"[/color]);
Microsoft.Win32.[color=#008080]RegistryKey[/color] rkCompany = rkSoftware.CreateSubKey([color=#800000]"poojo.com"[/color]);
Microsoft.Win32.[color=#008080]RegistryKey[/color] rkProgram = rkCompany.CreateSubKey(program);
[color=#0000ff]if[/color] (bIn == [color=#0000ff]true[/color]) {
rkProgram.SetValue([color=#800000]"Folder"[/color], folder, Microsoft.Win32.[color=#008080]RegistryValueKind[/color].String);
rkProgram.SetValue([color=#800000]"Common"[/color], common, Microsoft.Win32.[color=#008080]RegistryValueKind[/color].String);
rkProgram.SetValue([color=#800000]"Local"[/color], local, Microsoft.Win32.[color=#008080]RegistryValueKind[/color].String);
} [color=#0000ff]else[/color] {
folder = ([color=#008080]String[/color])rkProgram.GetValue([color=#800000]"Folder"[/color], folder);
}
} [color=#0000ff]catch[/color] ([color=#008080]Exception[/color] ex) {
[color=#008080]MessageBox[/color].Show([color=#800000]"Unable to use registry.\n"[/color] + ex.Message, [color=#800000]"Registry"[/color], [color=#008080]MessageBoxButtons[/color].OK);
}
}
 
Last edited by a moderator:
Back
Top