• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

MSFS C# SimConnect COM Exception 0xC00000B0 (Pipe Disconnected)

Messages
179
Country
panama
I has been getting this error or exception, which I know what means, that is:

STATUS_PIPE_DISCONNECTED
0xC00000B0

I has been researching in the web and there is very little information about it, the only main one is this:

I continue to get this error code with Simconnect. Can someone assist me? 0xC00000B0

If the pipe is disconnected unexpectedly without the sim crashing, then perhaps something illegal is going on with your use of the library. Are you using a lock or otherwise synchronizing on one thread when interacting with simconnect?

My program runs MULTIPLE threads, and I basically have few <List> variables of things that the MAIN (UI) thread needs to add to the tasks other BACKGROUND threads needs to process. In the MAIN (UI) thread, which is the one that opens a SimConnect connection with the Flight Simulator, I have few pieces of code like this:

Code:
// Enter this section ONE thread at a time!
lock (_locker)
{
    if (isQueueProcessing())
        soundQue.Add(new CSoundFileInfo(sFilename));
}

In the BACKGROUND thread, I have a code that is intended to copy the list "soundQue" list and transfer to another "sndsPlayList" list that is within the scope of the same BACKGROUND thread logic:

Code:
// Enter this section ONE thread at a time!
lock (_locker)
{
    if (soundQue.Count > 0)
    {
        // Transfer the list from "soundQue" to "sndsPlayList"
        sndsPlayList = new List<CSoundFileInfo>(soundQue);
        soundQue.Clear();
    }
}

So as per the link above, the threads synchronization somehow messes up with the Named Pipes connection used by the SimConnect library, but to be honest, I don't know, then what I could use to avoid this error to happen, and at the same time, still synchronize my threads to use the same SHARED memory resources, so they don't clash each other, which method is recommended to handle this situation so the program someone avoids this error from happening in the first place. Did anyone have the same experience with this kind of SimConnect error?

Any suggestion or recommendation is well received

Thanks,

Manuel
 
Hi Manuel,

I doubt we have enough information here for anyone to provide specific solutions. Assuming the exception is even related to multi-threading issues, these are generally not trivial to debug. Complete code, or perhaps better yet the simplest example which causes the issue, would definitely help (but I understand may not always be possible/practical).

Have you caught/examined this situation in a debugger?

Where/how are you seeing the 0xC00000B0 error code? Do you have it trapped in a try/catch somewhere... or the debugger comes up with that when the whole app crashes, or...?

Does the sim itself crash when this happens? Or just your application?

If you just comment out the shared vars access code (that you posted), does it stop crashing?

Basically the more you can narrow down the actual place/time of the exception, the better. The SimConnect error could also just be a "red herring," meaning some thread of the application has already crashed, and because of that the SimConnect session terminated perhaps, while another thread is still trying to use it... the app may then only report the SimConnect error on exit, but that is actually a result of whatever the original issue was.

Assuming this is directly related to SimConnect usage, probably the first thing I'd examine is which thread(s) are actually making SimConnect calls, and when are they doing so. For multi-threaded apps, I've found it most stable when there is only one thread receiving messages (the message dispatch loop/handler) and only one thread sending them (making calls to SimConnect functions). Trying to send from within a receive handler thread can be problematic (and especially shouldn't be changing "live" data, for example, a SimVar subscription for the var being currently handled). It is also possible to cause deadlocks this way, so one must pay attention (eg. multiple locks on shared mutexes, or trying to exit the message processing loop after a SimConnect QUIT message from within the message processor code itself).

EDIT: Invoking the same SimConnect instance from multiple threads is a definite no-no -- the functions/methods seem to be mostly re-entrant (though this isn't stated explicitly anywhere) but definitely not thread-safe (which is stated somewhere in the docs). There is also the async nature of the communication to contend with (there can be unpredictable delays between when a SC function is invoked and when the resulting action actually happens on the sim side). All SimConnect function calls from multiple threads must at least be locked so they're serialized, and even then they shouldn't be trying to operate on any "shared" features, like trying to change the same SimVar subscription, or set a value on one, or operate on the same Client Data area, just as a few examples.

HTH,
-Max
 
Last edited:
Thanks for your reply, Max!

I doubt we have enough information here for anyone to provide specific solutions. Assuming the exception is even related to multi-threading issues, these are generally not trivial to debug. Complete code, or perhaps better yet the simplest example which causes the issue, would definitely help (but I understand may not always be possible/practical).
I agree with you that I'm not providing enough information that might help you guys to help me, but also the code is huge, and the problem is, I don't know what exactly is causing it, I only have a hint from the link above, that says about a kind of issue that might be related to multi-threading synchronization. I reproduced only two times, but the users of my application reported to me back that it happens quite often, so it's a little difficult to reproduce, because it occurs randomly.

Have you caught/examined this situation in a debugger?
The time it happened to me, I tracked down to, moments after invoking a SimConnect function, meaning, the SimConnect connection was already dead (disconnected). Also, in the past, I think it was raised in the Windows form's message loop by a try-catch, but when I tried to examine the Call Stack, it just revealed that it came out from the SimConnect message loop.

Does the sim itself crash when this happens? Or just your application?
The sim continues running, but the Exception is received by my application. As a workaround, I coded a "re-connection" logic, so when this error pops up, I just trigger a routine to reconnect to SimConnect. The thing is I'm trying to identify what's exactly causing it, or at least have an idea or hint from other developers that might had the same error in the past.

If you just comment out the shared vars access code (that you posted), does it stop crashing?
The problem is that I can't completely comment that portion of the code because it's critical for my application functionality. I need to still synchronize with the other thread so it can fetch the list of strings added by the Main UI thread.

Basically the more you can narrow down the actual place/time of the exception, the better. The SimConnect error could also just be a "red herring," meaning some thread of the application has already crashed, and because of that the SimConnect session terminated perhaps, while another thread is still trying to use it... the app may then only report the SimConnect error on exit, but that is actually a result of whatever the original issue was.
A possible scenario like the one you described related to a thread deadlock makes sense to me, but I'm not sure how to reproduce it, I guess I would need to hard test until I get that error again. Also, I call SimConnect library functions from another BACKGROUND threads, and they work fine, when I call them from a BACKGROUND thread, but I'm not sure if this is a good practice do to so, from the Named Pipes and threading synchronization context or stand point. However, I really need to do it because, the BACKGROUND threads sets LVARs and they need to wait until these changes are applied in the sim, without freezing the MAIN UI thread, because the communications with the sim is done via SimConnect thru the Form's message loop running in the MAIN UI thread.

For multi-threaded apps, I've found it most stable when there is only one thread receiving messages (the message dispatch loop/handler) and only one thread sending them (making calls to SimConnect functions)
Like two separated threads? I guess the one receiving messages is the MAIN UI thread, and the other that sends or makes SimConnect calls as a BACKGROUND thread?

Thanks again,

Manuel
 
Hi Manuel,

Ah, intermittent and hard to reproduce... bummer! :-(

but the users of my application reported to me back that it happens quite often,

Clearly they're using it incorrectly! :)

The sim continues running, but the Exception is received by my application. As a workaround, I coded a "re-connection" logic, so when this error pops up, I just trigger a routine to reconnect to SimConnect.

OK, and you can recover your app, so that's good. My guess based on this is that the SimConnect client instance has quietly crashed/terminated/disconnected (possibly in another thread), so the next time it is used this exception pops up.

Concurrent access to the SimConnect instance (or instance data structs when parsing incoming messages) from multiple threads could do that. Though there are probably other ways to crash it as well.

I call SimConnect library functions from another BACKGROUND threads, and they work fine, when I call them from a BACKGROUND thread, but I'm not sure if this is a good practice do to so, from the Named Pipes and threading synchronization context or stand point.

Multiple background threads? Like workers? You definitely want to make sure they're not stepping on each other if sharing the same SimConnect client instance. You've mentioned locking the data structs the app uses, but not the actual SimConnect calls... but maybe you're already doing that. Anyway, as I said, I'd be looking into when/how exactly SimConnect methods are being invoked and making sure there's no possible concurrency, ever. If the issue only happens under heavy loads, for example, or very intermittently, that's another indicator of a possible concurrency.

Like two separated threads? I guess the one receiving messages is the MAIN UI thread, and the other that sends or makes SimConnect calls as a BACKGROUND thread?

For example, yes... Or it may make sense to run the incoming message processor on a background thread (also/instead). Invoking SimConnect functions is very fast (eg. to send a variable update or subscription), whereas processing (and/or reacting to) the incoming data may typically take longer. Depends on the application of course.... if the UI is used to display a lot of the data "raw" (w/out much/any processing) then it may not be worth the hassle of marshaling it back the main UI thread after every update.

But the main point I was trying to make again goes back to serializing SimConnect access as much as possible. It's really not meant for multi-threading at all, so I figure the fewer threads trying to use it, the better (and easier to keep track of).

I have no idea if this would work/help for your app, but another thought may be to use separate SimConnect instances in the worker threads. They'd each have to establish their own connection of course, and maybe other setup like data subscription, so that would add code and runtime overhead, but maybe worth it if you need high concurrency.... 🤷‍♂️

Cheers,
-Max
 
Ah, intermittent and hard to reproduce... bummer! :-(
Exactly!, this is one of those nasty bugs 😵‍💫

Clearly they're using it incorrectly!
🤣🤣🤣🤣🤣🤣🤣🤣 Indeed!

Concurrent access to the SimConnect instance (or instance data structs when parsing incoming messages) from multiple threads could do that. Though there are probably other ways to crash it as well.
I'm going to be honest, I didn't know that before....but as the old phrase says: "You learn something new everyday" 🥴....and I didn't experienced SimConnect concurrency issue before..... until recently....So it's a new lesson to be learned for me..... I assumed that it was working right, since during my tests it didn't have such issue, but after getting more and more users reports about this issue, then its something I can't ignore, neither blame on the users machine.

Multiple background threads? Like workers? You definitely want to make sure they're not stepping on each other if sharing the same SimConnect client instance. You've mentioned locking the data structs the app uses, but not the actual SimConnect calls... but maybe you're already doing that. Anyway, as I said, I'd be looking into when/how exactly SimConnect methods are being invoked and making sure there's no possible concurrency, ever. If the issue only happens under heavy loads, for example, or very intermittently, that's another indicator of a possible concurrency.
And this is where, I think, probably you just mentioned the possible source of all my problems. I did check and......yeah... 🥴, and I don't have any "lock" statement around SimConnect calls made from the "worker" (background) threads I made, so it's likely to be the root cause of the problems. In my application I just create like 5 worker threads, but there are 2 of them that actually makes SimConnect calls, and under some conditions it seems to reach "concurrency" and as a result, eventually, triggering the COM Exception (0xC00000B0). I was thinking to add the "lock" statement, but then, I was thinking that...the concurrency could be hit by calling a SimConnect call while the Main UI thread is receiving and processing SimConnect messages...and now I'm thinking that my best bet will be to make a second SimConnect client, as you suggested in the previous post, to only make SimConnect calls that write into LVARs in the sim, which is what the other 2 worker threads are doing, as well as using a SimConnect.

For example, yes... Or it may make sense to run the incoming message processor on a background thread (also/instead). Invoking SimConnect functions is very fast (eg. to send a variable update or subscription), whereas processing (and/or reacting to) the incoming data may typically take longer. Depends on the application of course.... if the UI is used to display a lot of the data "raw" (w/out much/any processing) then it may not be worth the hassle of marshaling it back the main UI thread after every update.

But the main point I was trying to make again goes back to serializing SimConnect access as much as possible. It's really not meant for multi-threading at all, so I figure the fewer threads trying to use it, the better (and easier to keep track of).
I have another question, Can I create a second SimConnect client without to be aasociated/mapped to a Windows handle?...right?

Thanks a LOT!

Manuel
 
Manuel: a really dirty trick I have used in the past is to stall a backgroundworker into a loop until I'm ready for it. Suppose I have two backgroundworkers:

- If backgroundworker1 has raised RunWorkerCompleted, I've set holdFlag2
- If backgroundworker2 has raised RunWorkerCompleted and backgroundworker1 is still executing RunWorkerCompleted and holdFlag2 is active, stall backgroundworker2 into a loop where it continuously checks to see if holdFlag2 is active
- When backgroundworker1 exits RunWorkerCompleted, the last action is to reset holdFlag2 and release backgroundworker2.
- Same actions apply if backgroundworker2 completes first; it raises holdFlag1

Because the main thread can only receive data serially, you can never get both threads vying for attention at the same time. It's dirty and requires crossthreading which needs to be carefully controlled, but it did work successfully. An equivalent of C/C++ semaphores in dotNet would be very nice but until it ever happens... (shrugs). However, this may not apply to what you are trying to do.

[Edit] 'An equivalent of C/C++ semaphores in dotNet would be very nice but until it ever happens' - EventWaitHandles. Gah. Missed that. Thanks Max!
 
Last edited:
Hi Manuel,

Yes, I think it would make sense to eliminate concurrency/threading issues first in this case. There may be something else going on as well, but multi-thread/concurrent access to same SimConnect instance should definitely be managed carefully (or avoided).

You could probably just lock using the instance variable itself...

C#:
SimConnect simconnect = new SimConnect(...);
lock(simconnect) {
    // invoke method(s) on simconnect instance
}

And you're right, you'll have to coordinate locking with the main thread as well, or anywhere that same SimConnect instance is being used, pretty much.

Depending on how you're invoking the message handlers, and what they're doing... you may be able to get away w/out a lock (around the simconnect.ReceiveMessage() call, for example, if you use one), but careful inside the handler callbacks (they're run on the same thread that invoked ReceiveMessage()).

Depending on what those "LVAR threads" are doing... do you need them to actually call SimConnect method(s)? For example, if they're doing calculations or monitoring/playing in the background, maybe they can post results back to the main thread (using events perhaps, or some other thread-safe manner), which then interacts with SimConnect. As I mentioned, invoking those SC method is generally very fast, so perhaps that's not a big burden for the main thread to handle.

Or a "dedicated" SimConnect thread which does all the SC interactions but runs separate from the main UI thread.

Can I create a second SimConnect client without to be aasociated/mapped to a Windows handle?...right?

Yes.

In fact a Window handle is never required. Even if one does need incoming message processing, this can be done with a generic "wait handle" instead. This allows all SC interaction to be moved to its own thread, even in UI-based applications.
I posted some more info about that in Read\write sim vars without a Windows App Handle thread.

Hope that helps!
-Max
 
Sorry by the delayed response guys, thanks a lot by the feedback and the suggestions to both of you!, I really appreciate it!.

After analyzing, the main UI thread basicly receives a lot of messages from SimConnect, in the applications where I use only LVARs, seems like concurrency is never hit, but there are applications where uses CDA (Client Data Areas), those most of the time hits concurrency and ending in the PIPE_DISCONNCTED error. The background threads I have basically, writes or sends simconnect variables (LVARs) or data into the CDAs, I think maybe I just avoid completely using the same instance across different threads, and use maybe a separated SimConnect instance, to be used only the the background threads, leaving alone the main UI thread, main, SimConnect handle.?

About the using a EventWaitHandle, is interesting concept!, I didn't know about it!, I'll check the link!

Depending on what those "LVAR threads" are doing... do you need them to actually call SimConnect method(s)? For example, if they're doing calculations or monitoring/playing in the background, maybe they can post results back to the main thread (using events perhaps, or some other thread-safe manner), which then interacts with SimConnect. As I mentioned, invoking those SC method is generally very fast, so perhaps that's not a big burden for the main thread to handle.

I like this idea!, do you mean like from the Background thread to send a kind of "PostMessage" with the variable that needs to be written to the main UI window right?, so like the Background thread doesn't calls directly the SimConnect methods?

Because the main thread can only receive data serially, you can never get both threads vying for attention at the same time. It's dirty and requires crossthreading which needs to be carefully controlled, but it did work successfully. An equivalent of C/C++ semaphores in dotNet would be very nice but until it ever happens... (shrugs). However, this may not apply to what you are trying to do.
Yeah, like kind of coordinating between threads, but I think it will be a little complex, because I'm a little afraid to produce a deadlocking scenario of some sort between them and the main UI.

Regards,

Manuel
 
Hi Manuel,

Sure, consolidating all related SC access to one thread makes sense, as long as that thread itself doesn't try to send messages concurrently (using the SC instance for a lock(), for example).
Or maybe just some helper function which does the actual SC calls inside a lock. Locking on the instance is key, I think, so all the calls to it get serialized.

A central place to make all SC calls can also be nice for centralized error catching and perhaps request tracking (so if you get EXCEPTION messages back from SC, you know what they're talking about... but that's a different topic really).
I use something like that here. This takes any SC method as the first argument, followed by any other argument(s) to pass on to that SC method. It also logs the request for SC error tracking, and catches/reports any exceptions.
I use something similar in my C++ based client which does a lot of CDA reading/writing, from a few threads (communicating with WASM module). Both implementations have proven robust.

If all these threads are sharing a CDA, definitely can see an issue there. That's essentially a "remote data structure" and need to be locked like any other shared resource. Which apparently SC doesn't take care of.

do you mean like from the Background thread to send a kind of "PostMessage" with the variable that needs to be written
Basically, yea.... You'd need some way to communicate safely between threads, and need a notification of when data/result is ready. Pretty typical "worker thread" scenario, really.
Using Events is pretty typical I believe... that's how SC itself delivers messages. Pretty much just a fancier name for callbacks... :)

Keep in mind I know practically nothing about your application, so this is all very general advice! :)

Cheers,
-Max
 
Back
Top