I always got a DisconnectedContext (a managed debugging assistant) when I run my application using Visual Studio. Given Google and docs, this can happen when COM objects on STA are called from other thread.
However, when I look throught all the threads when the popup appears, I don't find anything like this. (And I don't find anything weird at all).
Some ideas on how I can find the way the DisconnectedContext is raised?
Found this while looking for the same answer, thought I'd add a comment...
This error is virtually unavoidable in any multi-threaded app using CLR objects through in-process interop (on transient threads). The problem is that the CLR had non-deterministic cleanup of objects (which may be RCW's, with thread-affinity on the underlying COM objects). There's no way you can tell the runtime to clean up objects created on a thread (at least without creating another non-deterministic cleanup handle on the thread); it's a design limitation of the interop mechanism. Given that, there's no way to ever safely exit a thread which has created any CLR objects without potentially getting this error.
Best advice: don't use CLR/interop if you can help it. Next best advice: use COM+ to process-isolate your interop, so the CLR can live in a process which never terminates threads (use persistent thread pool or equivalent). Next best advice: join me in continuing to tell Microsoft about this design-level problem with their interop, and hope they fix it.
This is a pretty serious warning, don't ignore it. The scenario is that you created a COM object on a thread and that thread exited. But you keep using that object. COM takes care of objects that announced themselves to be not thread-safe (aka apartment threaded), it automatically marshals any calls on that object to the thread that created it. That can't work when that thread is no longer around.
Ignoring the warning can produce occasional and very hard to troubleshoot threading race errors. Stuff that goes subtly wrong only once a week. Review your code, pay attention to how the object that it complains about got created.
Related
So I've googled that it freezes because of using unsafe code, and AbortException throws only when control flow returns to managed code. So, in my case I have a native library, called in a thread. So sometimes I can't abort it, because the library is native and the Abort method not just do nothing, but freezes the calling thread.
So, I'd like to solve it.
For example, using a different process should help, but it's very complicated.
So, a less heavy solution is to use ' AppDomains' . But anyway I should create an exe and call it. I tried to generate it in memory like this
var appDomain = AppDomain.CreateDomain("newDomain");
var assemblyBuilder = appDomain.DefineDynamicAssembly(new AssemblyName("myAsm"), AssemblyBuilderAccess.RunAndCollect);
var module = assemblyBuilder.DefineDynamicModule("myDynamicModule");
var type = module.DefineType("myStaticBulder", TypeAttributes.Public);
var methBuilder = type.DefineMethod("exec", MethodAttributes.Static | MethodAttributes.Public);
var ilGenerator = methBuilder.GetILGenerator();
but I found only EMIT-way, it's very very complicated.
Does a superficial solution exist?
This cannot work by design. The CLR has very strict rules about what kind of code can safely be aborted. It is important, beyond the unwise use of Thread.Abort(), plenty of cases where the CLR must abort code, AppDomain unloads being foremost.
The iron-clad rule is that the CLR must be convinced that it is safe to abort the code. It is only convinced of that if the thread is busy executing managed code or is waiting on a managed synchronization object. Your case does not qualify, no way for the CLR to have any idea what that native code is doing. Aborting a thread in such a state almost never not causes problems. Same idea of the danger of Thread.Abort() but multiplied by a thousand. A subsequent deadlock on an internal operating system lock is very likely, utterly undebuggable.
An AppDomain therefore is not a solution either, it cannot be unloaded until the thread stopped running and it won't.
Only thing you can do is isolate that code in a separate process. Write a little helper EXE project that exposes its api through a standard .NET IPC mechanism like a socket, named pipe, memory mapped file, remoting or WCF. When the code hangs, you can safely Process.Kill() it. No damage can be done, the entire process state is thrown away. Recovering tends to be quite tricky however, you still do have to get the process restarted and get it back into the original state. Especially the state restoration is usually very difficult to do reliably.
Recently I worked with an external dll library where I have no influence on it.
Under some special circumstances, a method of this third party dll is blocking and never returning.
I tried to work around this issue by executing this method in a new AppDomain. After a custom timeout, I wanted to Unload the AppDomain and kill all this crap ;)
Unfortunately, it does not work - as someone would expect.
After some time it throws CannotUnloadAppDomainException since the blocking method does not allow aborting the thread gracefully.
I depend on using this library and it does not seem that there will be an update soon.
So can I work around this issue, even if it's not best practice?
Any bad hack appreciated :)
An AppDomain cannot typically solve that problem, it's only good to throw away the state of your program. The real issue is that your thread is stuck. In cases like these, calling Thread.Abort() is unlikely to work, it will just get stuck as well. A thread can only be aborted if it is a "alertable wait state", blocking on a CLR synchronization object. Or executing managed code. In a state that the CLR knows how to safely clean up. Most 3rd party code falls over like this when executing unmanaged code, no way to ever clean that up in a safe way. A decisive hint that this is the case is AppDomain.Unload failing to get the job done, it can only unload the AppDomain when it can abort the threads that are executing code in the domain.
The only good alternative is to run that code in a separate process. Which you can kill with Process.Kill(). Windows do the cleanup. You'd use a .NET interop mechanism to talk to that code. Like named pipes, sockets, remoting or WCF. Plus the considerable hassle of having to write the code that can detect the timeout, kills the process, starts it back up and recovers internal state since you now restart with an uninitialized instance of that 3rd party code.
Do not forget about the real fix. Create a small repro project that reproduces the problem. When it hangs, create a minidump of the process. Send both to the 3rd party support group.
after reading this (scroll down the end to Blocking Issues) I think your only solution is to run the method in a different process - this might involve quite a bit of refactoring and/or a 'host' project (eg Console application) that loads the method in question and makes it easy to call (eg reading args from command line) when launching the new process using the Process class
You can always use background worker, no need to create a new appdomain. This will ensure that you have complete control over the execution of the thread.
However, there is no way to ensure that you can gracefully abort the thread. As the dll is unmanaged, chances are there that it may cause memory leaks. However, spawning a new thread will ensure that your application does not crash when the Dll does not respond.
Extension to Release COM Object in C#
I noticed that saving the MailItem and releasing is a time consuming task. So, it is safe to do the following ? (pseudo-code below)
Thread 1 (main thread)
- Open 10 (different .msg files) - MailItems [List<MailItem> items]
- user works on them and want to save and close all of them with one click.
- On_save_All_click (runs on main thread)
- Do
- toBeClearedList.addAll(items);
- items.clear() [so that main thread cannot access those items]
- BG_Thread.ExecuteAsyn(toBeClearedList);
- End
Thread 2 (background thread) (input - List<MailItems>)
- foreach(MailItem item in input)
item.save();
System.Runtime.InteropServices.Marshal.ReleaseComObject(item)
- done
I wrote couple of tests and looks like its working; Just want to know if its safe to do so ? "Releasing COM objects in different thread than the one in which it was created"
Thanks
Karephul
When using COM from unmanaged code (C/C++), the rules are pretty strict: you can only call methods on an interface from the same apartment that you acquired the object on. So if you obtain an interface pointer on an STA thread, then only that thread is allowed to call any of the methods. If you obtain an interface pointer on an MTA thread, then only other threads in the same MTA can use that pointer. Any other use that crosses apartments requires that the interface pointer is marshaled to the other apartment.
However, that's unamanged world. .Net adds a whole layer on top of COM which buries a lot of these low-level details, and for the most part, once you get your hands on an interface, you can pass that interface around between threads as much as you please without having to worry about the old threading rules. What's happening here is that it are actually passing around references to an object called a "Runtime Callable Wrapper" (RCW), and it is managing the underlying COM interface, and controlling access to it accordingly. (It takes on the burden of upholding the COM apartment rules so that you don't have to, and that's why it can appear that the old COM threading rules don't apply in .Net: they do, they're just hidden from you.)
So you can safely call Release or other methods from another thread: but be aware that if the original thread was STA, then calling those methods will cause the underlying RCW to marshal the call back to the original owning thread so that it still upholds the underling COM rules. So using a separate thread may not actually get you any performance in the end!
Some articles worth reading that fill in some of the details here:
The mapping between interface pointers and runtime callable wrappers (RCWs) - good overview of some of the details of how RCW's work, but it doesn't say much about threading.
Improving Interop Performance - Marshal.ReleaseComObject - some good notes on when to use or not use ReleaseComObject, and how it works with the RCWs.
cbrumme's WebLog - Apartments and Pumping in the CLR - more internals than you're likely to want to know; this is a couple of CLR releases out of date, but still gives a good insight into how .Net covers over many of the underlying COM issues.
If I remember my COM properly (I always hated that technology, way too complicated), if the COM object is single-threaded (that is, belongs in a single-threaded-apartment), releasing it from another thread isn't going to do you any good - it's just going to execute the actual release code in your main thread.
You are going to see a little difference between your code, and releasing the objects from the main thread in one loop. If you release the objects in one loop, your UI is going to be unresponsive until you release all messages. By using a secondary thread, your UI thread will release one message, then handle other events, then release another, and so on. You can get the same effect by sending yourself a message (or using a Dispatcher if you have a WPF application), and avoid having another thread.
We have a very tricky interop problem wherein the thread used to initialize a 3rd-party system has to be the same thread used to terminate it. Failure to do this results in a deadlock. We are performing interop from a WCF service hosted in IIS. Currently this cleanup is done in disposal and normally works very well. Unfortunately, under heavy load IIS will do a rude unload and we never get to call dispose. We can move the shutdown logic into a critical finalizer but that doesn't help since we no longer have access to the initializing thread! At this point our only recourse seems to be notifying the CLR that the AppDomain is now likely in a corrupted state. However, I'm not sure how to do that (or if it's even possible). It may be that this is the utility of contracts at a class level but I admit I don't really understand those fully.
EDIT: Alternatively, this is could be viewed as a thread affinity problem in the finalizer. If anyone has a clever solution to that, I'm all ears :)
Try to split the code that depends on that native dependency to a standalone Windows service application if possible. If it cannot work well with WCF/IIS, you should avoid the conflicts instead of fighting against it.
This is a follow-on from:
Debugging a Multithreaded C# - C++/CLI - C++ Solution in Visual Studio 2008: What are these threads?
Please excuse the format, I've just repeated some of the description of the application here:
I've inherited a project consisting of three levels of code. The lowest layer is native C++ that interacts with hardware. This is mature, stable and well-tested. The intermediate level code is C++/CLI, which interacts with top-level C# code that contains the UI elements and some additional functionality. This C# code is incomplete and was rushed in development: it crashes frequently and is not fit for purpose. My task is debug it and complete it.
I received some very helpful info from the last question I asked - but now there's more issues! My problem at the moment is that when I invoke Application.Exit() to shut down the UI and quit the application, an exception is thrown:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute
I understand that this is because I need to ensure that all of my threads are ended before I call Application.Exit() (or Application.ExitThread()). I've tried using MainForm.Close() as quick fix while I investigate further but it doesn't alleviate the problem.
I don't want to just called Thread.CurrentThread.Abort(), mainly because some of the threads originate in the C++ section of the code, via Boost::Thread, and I'm unsure exactly what resources I may leave in an undesirable state (a lot of the code consists of objects for interaction with hardware, such as a serial port - it's not been implemented via RAII so I'm rather cautious of brute forcing things).
What I'd like to be able to do is identify what threads are doing what, and gracefully end them prior to exiting the application. However, in VS 2008, the stack trace - with 'Show External Code' activated - only reveals
[Native to managed transition]
[Managed to native transition]
so I'm still having difficulty tracing the individual native threads and thus working out the best way to end them.
I tried using Allinea DDTLite, which seemed excellent - but I've had some issues with my VS installation and I had to disable the plug-ins, so it wasn't a solution.
To summarise: what is the most effective way to ensure that all threads - both managed and native - are correctly finished so that the UI and then the
the entire application can exit cleanly?
What I'd like to be able to do is identify what threads are doing what
You cannot make this work. There are ways to enumerate the threads in a process, like the managed Process.Threads property or the native Thread32First/Next but you don't get nearly enough info about the threads to know what they do. And most certainly not to shut them down cleanly. Further complicated by the .NET framework using threads for its own purposes, like the debugger thread and the finalizer thread and a smattering of threadpool threads.
You can kill these threads rudely with TerminateThread, albeit that killing the finalizer thread will crash the program immediately, but that's no different from rudely terminating the process with Environment.Exit(). With the caveat that nothing is cleaned-up nicely. Windows will clean up most of the shrapnel though.
This should not normally be a problem. You know what threads you started, there should also be a mechanism to ask them to shut down. That's normally done by signaling an event, something that's tested in thread's main loop. Waiting on the thread handle confirms that the thread indeed exited. After which you can close the windows.
But that's probably plumbing that's missing, you'll have to add it. If the current native C++ code has no mechanism to take care of thread shutdown then you've got a fairly big problem. I'll guess that maintaining this native C++ code is the real problem. You may have to hire a gun to get this done.