Is SmsMessage not thread-safe? - c#

I'm writing an app for WM that handles incoming SMS events. I tried making it multi-threaded (using ThreadPool.QueueWorkItem) where the SmsMessage was passed along. However, I noticed that when I did that, the program would only handle the first sms event - afterwards, NO SMS were received by the device at all! But when the program exits, then all the missed SMSs arrived.
Based on that, I'd guess that the answer to my question is that SmsMessage objects are NOT thread-safe, even though there's not really an indication that that's the case.
So what if we want to try and thread an SmsMessage Object? I'll try that out tonight by making a copy of the SmsMessage (probably by using the constructor w/ item id), or I'll create an empty one and copy the fields manually.
DISCOVERY:
I narrowed down my problem. I was able to get everything to work in a background thread when I copied the SmsMessage into my own object, taking care not to reference any of the SmsMessage's objects. SMSs went flying through with no problem.
However, when I set up an MessageIntercepter to launch an application, and within that application instance, use a background thread to send an SMS, the application would work fine, but after it exits my code it crashes and displays the "There was an error in yourapp.exe" and asks me if you want to send the crash data to MS. I could never figure out what that error was, but I found out that if I sent the SMS from the same thread that launched the application, everything worked fine.
So, threading when the app is open = fine, as long as you don't pass/use the SmsMessage
Threading when the app is externally launched = fine, as long as you don't send an SmsMessage in another thread.

According to the MSDN Library (Microsoft.WindowsMobile.PocketOutlook.SmsMessage):
Any public static (Shared in Visual
Basic) members of this type are
thread-safe. Any instance members are
not guaranteed to be thread-safe.
So the answer to your question is: it is not thread-safe.
EDIT: I'm glad you managed to get this thing working. I'm pretty sure it's some race condition or unmanaged resource handling issue deep down in the PocketOutlook library.
Personally, I think you should keep all your messaging-related code in a single thread, from the point the MessageInterceptor created until the point it gets disposed and only pass objects that are written by you so you know that they don't have dodgy unmanaged dependecies (that's kind of what you did I think) - this should be enough to avoid these problems.
What's the point of having 2 SMS interceptor threads anyway? It's not like a phone could receive 2 text messages the same time.

Without seeing more code, it's hard to guess what's happening. I strongly suspect that it was a problem with your threading code rather than with SmsMessage.
If you could explain the architecture of your application, that would help a lot. I wouldn't be surprised to find you'd got a deadlock somewhere which was blocking everything.

Related

Might GC.Collect() be warranted in this particular case?

Disclaimer: Yes, I know that the general answer to whether or not to use GC.Collect() is a resounding "NO!". This is the first time in several years of programming that I ever consider using it at all.
Well then, here's the situation: We have developed a C# scripting tool based on the Microsoft.CodeAnalysis.CSharp.Scripting libraries (v3.6.0). It's a Winform GUI with editor etc., not unlike others out there. We use it for the validation of integrated circuits, meaning that its primary task is interfacing lab equipment such as power supplies, pattern generators, meters and the like. For the communication to said instruments we predominantly rely on National Instrument's VISA framework, albeit not exclusively. Some devices are controlled directly via DLLs from their respective manufacturers. In general, this system is working beautifully and by now it is successfully used by quite a lot of design engineers who do not know the first thing about the intricacies of .NET and C#.
At this point I should explain that the user can simply write a method (i.e. on "top-level") and then execute it. The Roslyn-part behind this is that the input is fed to CSharpScript.Create() and then compiled. The execution of a method is done via Script.ContinueWith("method name"). Inside of such a method the user can construct an object like, say, new VISA("connection string"), which connects to the device and then communicate with the device via this object. Nothing forces him or her to care about disposing the object (i.e. closing the connection).
Now, the problem is this: recently, very sporadic crashes of the GUI application have occurred with no feedback at all from the system - the form just closes and that's it. By trial-and-error we are currently 99% sure that if all connection objects are explicitely disposed within a method, the crashes do not occur. So, rewriting the method to something like this fixes the problem:
using(var device = new VISA("connection string"))
{
device.Query("IDN?");
}
The reason why I look into the GC's direction at all is that there is no discernible correlation to any actions from the user. The guys might run such methods for an hour without a problem and then, when scrolling in the editor, when no method is currently being executed, the GUI closes without comment. And that's why I'd like to get some input from people more knowledgeable about Roslyn and the GC:
Are there known issues with this scripting library and GC? (I would very much assume that there aren't)
Since the explicit disposal of objects seem to prevent the issue, might this be one of the extremely scarce situations where the use of GC.Collect() might be warranted? (admittedly, I could not yet test whether that also prevents the problem thanks to of home office)
Any ideas what can cause a .NET application to crash without any kind of feedback and how to obtain more information about such a crash? (the scripting engine is a separate DLL, as are the device drivers; the GUI only handles the graphics)
I am fully aware that this is a rather vague description of the problem with very little source code. This is due to the fact that the application comprises of quite a lot of source code and I have no idea what might be relevant here. Also, all namespaces in the above text refer to Microsoft.CodeAnalysis.CSharp.Scripting, except for VISA, which is self-defined. Obviously, I will gladly answer any follow-up questions for getting to the bottom of this.
Thanks in advance.
Short answer: No. It's not only not warranted, it's completely missing the actual issue.
Further explanation: #canton7 instantly hit the nail on the head when writing
I'd argue that your application shouldn't crash even if a finalizer does end up being called
The root issue hid inside a 3rd party DLL in form of an, at the very least, suboptimal implementation of IDisposable. Once I zoomed in on that, it was rather easy to produce a workaround for that.
My original question is so very misguided that I'd like to state the one that I should have asked:
How do I trace a crash of my C# application when my application's logging does not show anything?
This question has been answered comprehensively in a number of posts. In my case, the crash could be seen in the Windows event log.

if i don't use NetworkComms.Shutdown will i break something?

Hey i recently created a text message application in c# that sends messages back in forth in a console. I used NetworkCommsDotNet & NetworkCommsDotNet.Connections.
When i was researching about it i found a command NetworkComms.Shutdown() http://www.networkcomms.net/api/html/M_NetworkCommsDotNet_NetworkComms_Shutdown.htm
I'm also new to programming so i really didn't completely understand what they where saying and was still left wondering if I don't use this in my program, will it break something or mess up my router in any way?
ps - the program works and i had success with testing it between two computers on my home network.
I haven't used this, nor even know what it is, however i am good at reading documentation and believe what they tell me (for the most part)
Shutdown all connections, threads and execute OnCommsShutdown event.
Any packet handlers are left unchanged. If any network activity has
taken place this should be called on application close.
The reason why its telling you this, is that is most likely using unmanaged resources, and most likely wants to gracefully shut them down or clean them up. Since there is no open source for this project, we can only listen to what its telling you

COM Add-in: Resolve the error DisconnectedContext in WinWord.exe

I built an add-on to Microsoft Word. When the user clicks a button, it runs a number of processes that export a list of Microsoft Word documents to Filtered HTML. This works fine.
Where the code falls down is in processing large amounts of files. After the file conversions are done and I call the next function, the app crashes and I get this information from Visual Studio:
Managed Debugging Assistant 'DisconnectedContext' has detected a problem in 'C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE'.
Additional information: Transition into COM context 0x56255b88 for
this RuntimeCallableWrapper failed with the following error: System
call failed. (Exception from HRESULT: 0x80010100
(RPC_E_SYS_CALL_FAILED)). This is typically because the COM context
0x56255b88 where this RuntimeCallableWrapper was created has been
disconnected or it is busy doing something else. Releasing the
interfaces from the current COM context (COM context 0x56255cb0). This
may cause corruption or data loss. To avoid this problem, please
ensure that all COM contexts/apartments/threads stay alive and are
available for context transition, until the application is completely
done with the RuntimeCallableWrappers that represents COM components
that live inside them.
After some testing, I realized that if I simply remove all the code after the file conversions, there are no problems. To resolve this, I place the remainder of my code in yet another button.
The problem is I don't want to give the user two buttons. After reading various other threads, it sounds like my code has a memory or threading issue. The answers I am reading do not help me truly understand what to do next.
I feel like this is what I want to do:
1- Run conversion.
2- Close thread/cleanup memory issue from conversion.
3- Continue running code.
Unfortunately, I really don't know how to do #2 or if it is even possible. Your help is very much appreciated.
or it is busy doing something else
The managed debugging assistant diagnostic you got is pretty gobbledygooky but that's the part of the message that accurately describes the real problem. You have a firehose problem, the 3rd most common issue associated with threading. The mishap is hard to diagnose because this goes wrong inside the Word plumbing and not your code.
Trying not to commit the same gobbledygook sin myself, what goes wrong is that the interop calls you make into the Office program are queued, waiting for their turn to get executed. The underlying "system call" that the error code hints at is PostMessage(). Wherever there is a queue, there is a risk that the queue gets too large. Happens when the producer (your program) is adding items too the queue far faster than the consumer (the Office program) removes them. The firehose problem. Unless the producer slows down, the queue will grow without bounds and something is going to fail if it is allowed to grow endlessly, at a minimum the process runs out of memory.
It is not allowed to get close to that problem. The underlying queue that PostMessage() uses is protected by the OS. Windows fails the call when the queue already contains 10,000 messages. That's a fatal error that RPC does not know how to recover from, or rather should not try to recover from. Something is amiss and it isn't pretty. It returns an error code to your program to tell you about it. That's RPC_E_SYS_CALL_FAILED. Nothing much better happens in your program, the CLR doesn't know how to recover from it either, nor does your code. So the show is over, the interop call you made got lost and was not executed by Word.
Finding a completely reliable workaround for this awkward problem is not that straight-forward. Beware that this can happen on any interop call, so catching the exception and trying again is pretty drastically unpractical. But do keep in mind that the Q+D fix is very simple. The plain problem is that your program is running too fast, slowing it down with a Thread.Sleep() or Task.Delay() call is quite crude but will always fix the issue. Well, assuming you delay enough.
I think, but don't know for a fact because nobody ever posts repro code, that this issue is also associated with using a console mode app or a worker thread in your program. If it is a console mode app then try applying the [STAThread] attribute to your Main() method. If it is a worker thread then call Thread.SetApartmentState() before starting the thread, but beware it is very important to also create the Application interface on that worker thread. Not otherwise a workaround for an add-in.
If neither of those workarounds is effective or too unpractical then consider that you can automagically slow your program down, and ensure the queue is emptied, by occasionally reading something back from the Office program. Something silly, any property getter call will do. Necessarily you can't get the property value until the Office program catches up. That can still fail, there is also a 60 second time-out on the interop call. But that's something you can fix, you can call CoRegisterMessageFilter() in your program to install a callback that runs when the timeout trips. Very gobbledygooky as well, but the cut-and-paste code is readily available.

How to debug why application dies exception-less, when another application is closed?

I'm fixing bugs on an application, that is kind of data consumer/worker, getting data from third party application, using supplied API and libraries for doing so. It's c++ based API and the .net application is using a bit of c++ to access the libraries. Also - the application is multi-threaded, it's windowed (Winforms), uses several third party libraries (nhibernate, mysql and others). It might be relevant to add, that our consumer thread is the only place in the code, when it accesses the c++ library.
The problem? When the producent application is closing (takes a bit more time, more than a minute), consumer application dies within seconds, without error/exception - even thought they're opened independently. No information in Event Log, no Dr. Watson action, no exceptions in Visual Studio (debug just stops).
I've tried:
Stepping throughout the code to see the moment, where it closes, but it always happened in different places, was it calling the producent's libraries code, or not.
Debugged the application with Visual Studio configured to break on any exception throwing - but it dies without a thing.
Creating crash dumps (using ADPlus.vbs) and using windbg on them (I'm new to such low-level debugging, though), but !analyze resulted with different stack traces - leaving me traceless.
What would be the good direction to find out why the consumer application dies? Is there a way, to get around the problem (like showing a prompt message to the user, like: "Producent application is closing, consumer application will do the same!")?
[EDIT]
Consumer application is multi-threaded, and it's one consumer thread as addon to UI thread. Also - the third party app we're using as producer uses COM to send information to any consumer app (aka add-on).
Me and my coworker decided to comment out some code, to find the code, that possibly makes the problem. And probably we've found it - the application dies if and only if we've registered our consumer to producer. After reading documentation for the third party app, it turned out that consumer apps have to actively query for message of closing the producer, otherwise they would be forcefully terminated by the producer app.
So: 95% that the problem is third party application which we're querying for data is sending COM message to forcefully terminate our application (I'll post info / change to wiki, if we'd test it's the only reason).
The general scenario described here is a source for a very common confusion and misunderstanding related to cases where one tries to understand 'how come my application vanished into thin air without leaving any trace?'.
The immediate assumtion would be: my application 'died' or 'crashed' or 'encountered such unexpected exception, which is even not visible to the debugger and thus did not create any dump-file. Happened to me few good times...
The real answer in most cases would be that the application did not realy crash or die and did not receive any excpetion, but was simply shutted-down gracefully, but from a flow that I did not expect.
The easiest way to debug such cases will be to put a breakpoint in kernel32!ExitProcess and to follow the stack and see how we got here.
Hope this helps
It turns out, that its the host application, that kills my application. The proper way to debug the problem was to spy on windows messages and to see, that my application is getting Process Terminate message.

SslStream responds differently when accessed as COM object

I am working with an on a project where the bulk of the code is C++. The shop is migrating to C# in the long run, so where possible we are making new code in C# and exposing to C++ via COM.
I have wrapped an System.Net.Sockets.SslStream and a little bit of other functionality in a COM object that is intended to send and then receive messages. When calling the functions on this class from a test C# program I am able to send and receive messages without issue. Making the same calls, which are exposed via COM, seems to work as well, except I cannot receive data immediately after I send.
From the C# test data sends and receives quite quickly and I get the responses I should. From C++ I always get timeout errors. The data in the functions making the call to Read is identical in the C# test and from the C++ program. Much of the state in the SslStream is identical. Just after the write call and before the Read the only differences appear to be, several handles and what appear to be memory addressest, but I assume those are not important. At this same time I noticed that in an item called 'base', then inside an item called 'InnerStream', then inside 'System.Net.Sockets.NetworkStream' there is a property called 'DataAvailable'. This is true in the C# test where it works and false in the C++ program where it fails. I am not aware of any meaningful difference between these project beyond what I have described.
I can provide further details about troubleshooting or snippets of code. I have not included code here because tjust the pieces related to the problem would still be immense. I hope there is some kind of magic answer as to what is going on, however the error is almost certainly in depth and very specific. I would appreciate anything that provides insight on further troubleshooting steps.
What kinds of complications does calling C# though COM impose that I may not have taken in account?
Where did the other sides message go if not into the SslStream buffer?
Where should I be looking?
I have discovered the answer, and it is unrelated to COM, C#, C++ and instead has to do with the formatting of the message being sent between the systems involved. The other system uses an extra carriage return to indicate the end of the message. When missing the remote system simply stops responding until another SSL session is started.
At a previous point in the project I was including an extra line break at the end of messages sent to the server. I had copied one of these messages to produce my entirely c# test. Several times I also took the messages being sent from both codebases and put them into a merge/diff viewer. I never noticed this difference because I had disabled white space matching.
From now on when I compare raw output to other raw output, I will make sure that none of my tools will hide differences from me.

Categories