I have a program that retrieves data from a serial device, and then puts it in a server that is accessible by certain programs that can handle this protocol. This server is a third party program that is in the form of an active x control.
The hardware devices require a Thread.Sleep, which is unfortunate. The programs that monitor the server sometimes query the server during the time when a thread is sleeping. This causes it to think the server has failed.
My next idea was to put the server on a separate thread, one solely dedicated for the server tasks. In the UI thread, I run the following code:
Thread workerThread = new Thread(DoServerWork);
workerThread.SetApartmentState(ApartmentState.STA);
workerThread.Start();
In the delegate, I have
public void DoServerWork()
{
rtu = new AxASMBSLVLib.AxASMBSLV();
rtu.CreateControl();
rtu.BeginInit();
rtu.OpenPort();
while (true)
{
}
}
The problem is that the server starts to work, and then becomes unresponsive in about 5 seconds. My initial thought is that the thread is exiting, but the while(true) should prevent that from happening. Any thoughts?
Since you are running this in a Single Threaded Apartment (STA), once that thread hits the empty endless loop, nothing more can happen. An endless loop is generally not a good idea. You should probably use a timer to periodically perform the server work in its OnElapsed event handler.
It is a modbus TCP/IP slave from a third party company. The first option is to "drag and drop" it from the toolbox to the GUI, causing it to be on the UI thread.
Since ActiveX requires STA : exactly the right thing.
I must call Thread.Sleep on the UI thread,
that should never be necessary, here lies your real problem. Never block/sleep he main thread.
Your question should be about how to avoid the Sleep().
Related
My application is a communications server that receives TCP messages from a web server and then re-broadcasts the message to a number of iPads. It's a windows forms application in C#. Program.cs creates an instance of the primary form and then that form creates four threads that do the communications work. There is a thread that listens for messages from the web server, a thread that processes the incoming messages into the data that needs to be transmitted and a thread that handles sending the outbound messages. The fourth thread does database cleanup and spends 99% of it's time sleeping.
The problem I'm seeing is the GUI locks up with a load is placed on the system. On incoming message may represent 50 or 100 outgoing messages. While testing I'm restricting they system to only send 5 messages out at a time, so it requires a longer transmission time. The sending process is using async call backs, but even it it wasn't, I can't understand why load on the tread could be stalling the GUI thread.
I'm removed a much of the cross thread communications from the thread to the GUI for status update. The pattern for communications to the GUI is:
public void StatusOutput(string myString)
{
if (this.lbStatus.InvokeRequired)
{
this.lbStatus.BeginInvoke(new DebugOutputInvoker(StatusOutput), myString);
}
else
{
lbStatus.Items.Add(myString);
while (lbStatus.Items.Count >= 501)
{
lbStatus.Items.RemoveAt(0);
}
lbStatus.SelectedItem = lbStatus.Items.Count - 1;
} // StatusUpdate() ...
Can anyone give me any advice on how to pursue this? I though threads were completely isolated from the GUI and couldn't load it.
Thanks!
As an update, I removed all thread to GUI communications and the GUI stopped locking up. So this proved it wasn't a GUI thread issue. I work through the threads till I found out it's the TCPSender thread that has a lot of async callback functions, potentially hundreds of them. When ever this thread get's busy with it's async calls, the GUI locks up. I suspect it has to do with call backs happening while the thread has one of the GUI's methods in process.
I've solved the issue with making a new thread that just collects data from the operational threads and then updates the user interface. General status message that were transferred to the status display on the GUI thread are now queued and updated to the GUI through this new thread.
The GUI remains responsive and actually seems to be able to display more data now.
Assume that you have a multi-threaded Windows service which performs lots of different operations which takes a fair share of time, e.g. extracting data from different data stores, parsing said data, posting it to an external server etc. Operations may be performed in different layers, e.g. application layer, repository layer or service layer.
At some point in the lifespan of this Windows service you may wish to shut it down or restart it by way of services.msc, however if you can't stop all operations and terminate all threads in the Windows service within the timespan that services.msc expects to be done with the stop procedure, it will hang and you will have to kill it from Task Manager.
Because of the issue mentioned above, my question is as follows: How would you implement a fail-safe way of handling shutdown of your Windows service? I have a volatile boolean that acts as a shutdown signal, enabled by OnStop() in my service base class, and should gracefully stop my main loop, but that isn't worth anything if there is an operation in some other layer which is taking it's time doing whatever that operation is up to.
How should this be handled? I'm currently at a loss and need some creative input.
I would use a CancellationTokenSource and propagate the cancellation token from the OnStop method down to all layers and all threads and tasks started there. It's in the framework, so it will not break your loose coupling if you care about that (I mean, wherever you use a thread/Task you also have `CancellationToken' available.
This means you need to adjust your async methods to take the cancellation token into consideration.
You should also be aware of ServiceBase.RequestAdditionalTime. In case it is not possible to cancel all tasks in due time, you can request an extension period.
Alternatively, maybe you can explore the IsBackground alternative. All threads in your windows service that have this enabled are stopped by the CLR when the process is about to exit:
A thread is either a background thread or a foreground thread.
Background threads are identical to foreground threads, except that
background threads do not prevent a process from terminating. Once all
foreground threads belonging to a process have terminated, the common
language runtime ends the process. Any remaining background threads
are stopped and do not complete.
After more research and some brainstorming I came to realise that the problems I've been experiencing were being caused by a very common design flaw regarding threads in Windows services.
The design flaw
Imagine you have a thread which does all your work. Your work consists of tasks that should be run again and again indefinitely. This is quite often implemented as follows:
volatile bool keepRunning = true;
Thread workerThread;
protected override void OnStart(string[] args)
{
workerThread = new Thread(() =>
{
while(keepRunning)
{
DoWork();
Thread.Sleep(10 * 60 * 1000); // Sleep for ten minutes
}
});
workerThread.Start();
}
protected override void OnStop()
{
keepRunning = false;
workerThread.Join();
// Ended gracefully
}
This is the very common design flaw I mentioned. The problem is that while this will compile and run as expected, you will eventually experience that your Windows service won't respond to commands from the service console in Windows. This is because your call to Thread.Sleep() blocks the thread, causing your service to become unresponsive. You will only experience this error if the thread blocks for longer than the timeout configured by Windows in HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout, because of this registry value this implementation may work for you if your thread is configured to sleep for a very short period of time and does it's work in an acceptable period of time.
The alternative
Instead of using Thread.Sleep() I decided to go for ManualResetEvent and System.Threading.Timer instead. The implementation looks something like this:
OnStart:
this._workerTimer = new Timer(new TimerCallback(this._worker.DoWork));
this._workerTimer.Change(0, Timeout.Infinite); // This tells the timer to perform the callback right now
Callback:
if (MyServiceBase.ShutdownEvent.WaitOne(0)) // My static ManualResetEvent
return; // Exit callback
// Perform lots of work here
ThisMethodDoesAnEnormousAmountOfWork();
(stateInfo as Timer).Change(_waitForSeconds * 1000, Timeout.Infinite); // This tells the timer to execute the callback after a specified period of time. This is the amount of time that was previously passed to Thread.Sleep()
OnStop:
MyServiceBase.ShutdownEvent.Set(); // This signals the callback to never ever perform any work again
this._workerTimer.Dispose(); // Dispose of the timer so that the callback is never ever called again
The conclusion
By implementing System.Threading.Timer and ManualResetEvent you will avoid your service becoming unresponsive to service console commands as a result of Thread.Sleep() blocking.
PS! You may not be out of the woods just yet!
However, I believe there are cases in which a callback is assigned so much work by the programmer that the service may become unresponsive to service console commands during workload execution. If that happens you may wish to look at alternative solutions, like checking your ManualResetEvent deeper in your code, or perhaps implementing CancellationTokenSource.
I am working on a project in C#.NET using the .NET framework version 3.5.
My project has a class called Focuser.cs which represents a physical device, a telescope focuser, that can communicate with a PC via a serial (RS-232) port. My class (Focuser) has properties such as CurrentPosition, CurrentTemperature, ect which represents the current conditions of the focuser which can change at any time. So, my Focuser class needs to continually poll the device for these values and update its internal fields. My question is, what is the best way to perform this continual polling sequence? Occasionally, the user will need to switch the device into a different mode which will require the ability to stop the polling, perform some action, and then resume polling.
My first attempt was to use a time that ticks every 500ms and then calls up a background worker which polls for one position and one temperature then returns. When the timer ticks if the background worker isBusy then it just returns and tries again 500ms later. Someone suggested that I get rid of the background worker all together and just do the poll in the timer tick event. So I set the AutoReset property of the timer to false and then just restart the timer every time a poll finishes. These two techniques seemed to behave the exact same way in my application so I am not sure if one is better than the other. I also tried creating a new thread every time I want to do a poll operation using a new ThreadStart and all that. This also seemed to work fine.
I should mention one other thing. This class is part of a COM object server which basically means that the class library that is produced will be called upon via COM. I am not sure if this has any influence on the answer but I just thought I should throw it out there.
The reason I am asking all of this is that all of my test harness runs and debug builds work just fine but when I do a release build and try to make calls to my class from another application, that application freezes up and I am having a hard time determining the cause.
Any advice, suggestions, comments would be appreciated.
Thanks, Jordan
Remember that the timer hides its own background worker thread, which basically sleeps for the interval, then fires its Elapsed event. Knowing that, it makes sense just to put the polling in Elapsed. This would be the best practice IMO, rather than starting a thread from a thread. You can start and stop Timers as well, so the code that switches modes can Stop() the Timer, perform the task, then Start() it again, and the Timer doesn't even have to know the telescope IsBusy.
However, what I WOULD keep track of is whether another instance of the Elapsed event handler is still running. You could lock the Elapsed handler's code, or you could set a flag, visible from any thread, that indicates another Elapsed() event handler is still working; Elapsed event handlers that see this flag set can exit immediately, avoiding concurrency problems working with the serial port.
So it looks like you have looked at 2 options:
Timer. The Timer is non-blocking while waiting (uses another thread), so the rest of the program can continue running and be responsive. When the timer event kicks off, you simply get/update the current values.
Timer + BackgroundWorker. The background worker is also simply a separate thread. It may take longer to actually start the thread than to simply get the current values. Unless it takes a long time to get the current values and causes your program to become unresponsive, this is unnecessary complexity.
If getting values is fast enough, stick to #1 for simplicity.
If getting values is slow, #2 will work but unnecessarily has a thread start a thread. Instead, do it with only a BackgroundWorker (no Timer). Create the BackgroundWorker once and store in a variable. No need to recreate it every time. Make sure to set WorkerSupportsCancellation to true. Whenever you want to start checking values, on your main program thread do bgWorker.RunWorkerAsync(). When you want to stop, do bgWorker.CancelAsync(). Inside your DoWork method, have a loop that checks the values and does a Thread.Sleep(500). Since it's a separate thread, it won't make your program unresponsive. In the loop conditions, also check to see if the polling was cancelled and break out. You'll probably need a way to get the values back to the main thread. You can use ReportProgress() if an integer is good enough. Otherwise you can create an object to hold the content, but make sure to lock (object) { } before reading and modifying it. This is a quick summary, but if you go this route I would recommend you read: http://www.albahari.com/threading/part3.aspx#_BackgroundWorker
Is the process of contacting the telescope and getting the current values actually take long enough to warrant polling? Have you tried dropping the multithreading and just blocking while you get the current value?
To answer your question, however, I would suggest not using a background worker but an actual Thread that updates the properties continuously.
If all these properties are read only (can you set the temp of the telescope?) and there are no dependencies between them (e.g., no transactions are required to update multiple properties at once) you can drop all the blocking code and let your thread update willy-nilly while other threads access the properties.
I suggest a real, dedicated Thread rather than the thread pool just because of a lack of knowledge of what might happen when mixing background threads and COM servers. Also, apartment state might play into this; with a Thread you can try STA but you can't do that with a threadpool thread.
You say the app freezes up in a release build?
To eliminate extra variables, I'd take all the timer/multi-threaded code out of the application(just comment it out), and try it with a straightforward blocking method.
i.e. You click a button, it calls a function, that function hits the COM object for data, and then updates the UI. All in a blocking, synchronous fashion. This will tell you for sure whether it's the multi-threading code that's freezing you up, or if it's the COM interaction itself.
How about starting a background thread with ThreadPool? Then enter a loop based on a bool (While (bContinue)) that loops and does your work and then a Thread.Sleep at the end of the loop - exiting the program would include setting bContinue to false so the thread stops - perhaps hook it up to the OnStop event in a windows service
bool bRet = ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc));
private void ThreadFunc(object objState)
{
// enter loop
bContinue = true;
while (bContinue) {
// do stuff
// sleep
Thread.Sleep(m_iWaitTime_ms);
}
}
I have a piece of code where I send a file content over tcp/ip channel. There are times when this connection hangs causing entire application to freeze. Is there a way for my main thread to spawn a worker thread and monitor that worker thread. If worker thread succeeds, well and good. If it hangs , the main thread could log error message and continue. How can I simulate in my test code that a worker thread is hanging. please let me know what could the code look like. I am using C# Visual studio 2002.
Surely this is possible.
Either you implement threading manually using the BackgroudWorker or Thread class or (in your case even simpler) you use the asynchroneous methods for sending your content.
All the network related classes contain asynchroneous methods for their operations. Look for the methods that contain Async or Begin...
And simulating a dead thread is simple. Just make an endless loop:
while (true)
System.Threading.Thread.Sleep (10);
We have a WinForms desktop application, which is heavily multithreaded. 3 threads run with Application.Run and a bunch of other background worker threads. Getting all the threads to shut down properly was kind of tricky, but I thought I finally got it right.
But when we actually deployed the application, users started experiencing the application not exiting. There's a System.Threading.Mutex to prevent them from running the app multiple times, so they have to go into task manager and kill the old one before they can run it again.
Every thread gets a Thread.Join before the main thread exits, and I added logging to each thread I spawn. According to the log, every single thread that starts also exits, and the main thread also exits. Even stranger, running SysInternals ProcessExplorer show all the threads disappear when the application exits. As in, there are 0 threads (managed or unmanaged), but the process is still running.
I can't reproduce this on any developers computers or our test environment, and so far I've only seen it happen on Windows XP (not Vista or Windows 7 or any Windows Server). How can a process keep running with 0 threads?
Edit:
Here's a bit more detail. One of event loops is hosting an Win32 interop DLL which uses a COM object to talk to a device driver. I put it in its own thread because the device driver is time sensitive, and whenever the UI thread would block for a significant amount of time (such as waiting for a database call to finish), it would interfere with the device driver.
So I changed the code so the main thread would do a Thread.Join with the device driver thread. That actually caused the application to lock up... it logs a few more calls on the UI thread after the Join completed and then everything stops. If the device is powered off, the driver never starts, and the problem goes away. So it looks like the driver must be responsible for keeping the application alive, even after it's supposedly been shut down.
When you create your threads, set IsBackground=true on them. When your main ui thread/app is closed, all created threads will automatically be shut down.
http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx
Is it possible that the children of your Application.Run calls aren't terminating? Also, what's actually causing the application to exit - does it automatically close when all the threads have terminated (automatically meaning you wrote some code to do that), or is it user-imitated?
I had an issue once where there was a race condition in my "thread complete" event code that would sometimes result in what you're seeing. The last two threads would finish at the same time, fire the event simultaneously, and each event would decide it wasn't the last thread, so the application would continue running, even though the thread count was zero. To resolve this, I was able to find and eliminate the race condition, but you could also use a timer that checks every second or two, gets a count of the threads, and if none are still open, it kills the application.
We never did figure out the root programmatic cause, but it was a specific driver version that caused the issue, and upgrading to a new driver fixed the problem.
Unfortunately, this is all the answer I can give, if someone else someday runs into a similar problem...