Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Console Thread

I have a program that uses the console and GUI for quite important aspects of my program. I presume that these two parts both use the same thread.

The issue is that I'm using a multimeter with an output, and to receive bits of data from it the program sends commands to do it - it uses SCPI, these commands run through the console.

The issue is, whenever I send a command to the multimeter it makes the program become unresponsive until it has received the data back, I know why and I also know how to fix it, but I'm wondering if there is a better way.

Currently I'm changing the default thread that the GUI runs on:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Thread applicationThread = new Thread(() => Application.Run(new Form1()));
    applicationThread.SetApartmentState(ApartmentState.STA);
    applicationThread.Start();
}

This stops the program becoming unresponsive when I send commands to the meter, but I'm not 100% sure if this will create any other issues I've yet to see?

My questions are:

  • Is there a better way to change the thread that the GUI runs on?
  • If not, will this method create any issues I've yet to see?
  • Could I change the Console thread instead?
like image 377
Johnathan Brown Avatar asked Oct 19 '22 05:10

Johnathan Brown


1 Answers

[STAThread]
static void Main()

This is very unwise, you are breaking the STAThread contract. Which stipulates that you must pump a message loop. Application.Run() in a .NET program. You did this correctly for the thread that displays the UI but not for the main thread. The one you presumably use to talk to the meter.

Worst problem is that it will easily look like you'll get away with it. But it is a ticking time-bomb that's ready to blow up in your face at any time. Misbehavior ranges from arbitrary deadlock, particularly the nasty kind that makes the finalizer thread of a .NET program hang. Happens when the CLR tries to release the COM interop wrapper. Very hard to diagnose, your program ultimately falls over when it runs out of memory. Takes a while, invariably longer than your patience testing the app. To random misbehavior of the meter object itself, usually diagnosed by a call on the object deadlocking or the object not raising an expected event.

The finalizer thread deadlock is certainly the worst problem, bad enough to force you to change this. Focus on the real issue, it is the meter code that's misbehaving. Give it a safe haven by itself, a properly constructed STA thread that pumps. You'll find boiler-plate code in this post. Or just change the attribute to [MTAThread], that forces COM to provide a safe haven for the COM object by itself. But best to take the bull by its horn so you know what's going on instead of relying on undebuggable black magic.

I'd also strongly recommend a support call to the vendor or author of this component. Apartment-threaded COM servers should not behave this way. Something is out of whack.

like image 107
Hans Passant Avatar answered Nov 15 '22 04:11

Hans Passant