A threading problem where mono hangs and MS.Net doesn't - multithreading

I'm testing my app with mono in prevision of a Linux port, and I have a threading problem. I initially considered pasting 3000 code lines here, but finally I've devised a small minimal example ;)
You have a form with a button (poetically named Button1, and a label (which bears, without surprise, the name Label1)). The whole lot is living a happy life on a form called Form1. Clicking Button1 launches an infinite loop that increments a local counter and updates Label1 (using Invoke) to reflect its value.
Now in Mono, if you resize the form, the label stops updating, never to restart. This doesn't happen with MS implementation. BeginInvoke doesn't work any better; worse, it makes the UI hang in both cases.
Do you know where this discrepancy comes from? How would you solve it? And finally, why doesn't BeginInvoke work here? I must be making a huge mistake... but which?
EDIT:
Some progress so far:
Calling BeginInvoke does in fact work; only, the UI just doesn't refresh fast enough, so it seems to stop.
On mono, what happens is that the whole thread hangs when you insert a message in the UI queue (eg by resizing the form). In fact, the synchronous Invoke call never returns. I'm trying to understand why.
Of interest: even using BeginInvoke, the asynchronous calls don't get executed before the resizing operation ends. On MS.Net, they keep running while resizing.
The code looks like this (C# version lower):
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim T As New Threading.Thread(AddressOf Increment)
T.Start()
End Sub
Sub UpdateLabel(ByVal Text As String)
Label1.Text = Text
End Sub
Delegate Sub UpdateLabelHandler(ByVal Text As String)
Sub Increment()
Dim i As Long = 0
Dim UpdateLabelDelegate As New UpdateLabelHandler(AddressOf UpdateLabel)
Try
While True
i = (i + 1) Mod (Long.MaxValue - 1)
Me.Invoke(UpdateLabelDelegate, New Object() {i.ToString})
End While
Catch Ex As ObjectDisposedException
End Try
End Sub
End Class
Or, in C#,
public class Form1
{
private void Button1_Click(System.Object sender, System.EventArgs e)
{
System.Threading.Thread T = new System.Threading.Thread(Increment);
T.Start();
}
public void UpdateLabel(string Text)
{
Label1.Text = Text;
}
public delegate void UpdateLabelHandler(string Text);
public void Increment()
{
long i = 0;
UpdateLabelHandler UpdateLabelDelegate = new UpdateLabelHandler(UpdateLabel);
try {
while (true) {
i = (i + 1) % (long.MaxValue - 1);
this.Invoke(UpdateLabelDelegate, new object[] { i.ToString() });
}
} catch (ObjectDisposedException Ex) {
}
}
}

This is a bug in the mono runtime, at least I think it is. The code might not be good practice (I'm not a threading expert), but the thing that suggests a bug is the fact that the behaviour differs on windows and Linux.
On Linux, mono has exactly the same behaviour as MS.Net has on windows. No hanging, continuous updates even while resizing.
On Windows, mono displays all the aforementioned problems. I've posted a bug report at https://bugzilla.novell.com/show_bug.cgi?id=690400 .

Do you know where this discrepancy
comes from? How would you solve it?
I am not sure. I do not see anything obvious in your code that would cause the difference between Mono and .NET. If I had to make a wild guess I would say there is a possibility that you have stumbled upon an obscure bug in Mono. Though, I suppose it is possible that Mono uses a sufficiently different mechanism for handling the WM_PAINT messages that cause the form to get refreshed. The constant pounding of the UI thread from repeated calls to Invoke may be disrupting Mono's ability to get the form refreshed.
And finally, why doesn't BeginInvoke
work here?
Calling Invoke in a tight loop is bad enough, but BeginInvoke will be even worse. The worker thread is flooding the UI message pump. BeginInvoke does not wait until the UI thread has finished executing the delegate. It just posts the requests and returns quickly. That is why it appears to hang. The messages that BeginInvoke is posting to the UI message queue keep building up as the worker thread is likely severely out pacing the UI thread's ability to process them.
Other Comments
I should also mention that the worker thread is nearly useless in the code. The reason is because you have a call to Invoke on every iteration. Invoke blocks until the UI has finished executing the delegate. That means your worker thread and UI thread are essentially in lock-step with each other. In other words, the worker is spending most of its time waiting for the UI and vice versa.
Solution
One possible fix is to slow down the rate at which Invoke is called. Instead of calling it on every loop iteration try doing it every 1000 iterations or the like.
Any even better approach is to not use Invoke or BeginInvoke at all. Personally, I think these mechanisms for updating the UI are way overused. It is almost always better to let the UI thread throttle its own update rate especially when the worker thread is doing continuous processing. This means you will need to place a timer on the form and have it tick at the desired refresh rate. From the Tick event you will probe a shared data structure that the worker thread is updating and use that information to update the controls on the form. This has several advantages.
It breaks the tight coupling between the UI and worker threads that Control.Invoke imposes.
It puts the responsibility of updating the UI thread on the UI thread where it should belong anyway.
The UI thread gets to dictate when and how often the update should take place.
There is no risk of the UI message pump being overrun as would be the case with the marshaling techniques initiated by the worker thread.
The worker thread does not have to wait for an acknowledgement that the update was performed before proceeding with its next steps (ie. you get more throughput on both the UI and worker threads).

First and foremost: clicking on Button1 is asynchronous already, so you don't need to create another thread to increment, just call the increment method Sorry, I was reading your question line by line and by the time I got to the while-loop I forgot about the button:
private void Button1_Click(System.Object sender, System.EventArgs e)
{
Thread t = new Thread(Increment);
t.IsBackground = true;
t.Start();
}
Second: if you do need to use a thread then you should always set your thread to background (i.e. foreground prevents your process from terminating), unless you have a good reason for using a foreground thread.
Third: if you're making updates to the UI, then you should check the InvokeRequired property and call BeginInvoke:
public void UpdateLabel(string Text)
{
if (InvokeRequired)
{
BeginInvoke(new UpdateLabelDelegate(UpdateLabel), Text);
}
else
{
Label1.Text = Text;
}
}
public void Increment()
{
int i = 0;
while(true)
{
i++; // just incrementing i??
UpdateLabel(i.ToString());
Thread.Sleep(1000);// slow down a bit so you can see the updates
}
}
You can also "automate" the Invoke Required "pattern": Automating the InvokeRequired code pattern
And now see if you're still having the same problem.
I tried it on my machine and it works like a charm:
public partial class Form1 : Form
{
private delegate void UpdateLabelDelegate(string text);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(Increment);
t.IsBackground = true;
t.Start();
}
private void UpdateLabel(string text)
{
if (label1.InvokeRequired)
{
BeginInvoke(new UpdateLabelDelegate(UpdateLabel), text);
}
else
{
label1.Text = text;
}
}
private void Increment()
{
int i = 0;
while (true)
{
i++;
UpdateLabel(i.ToString());
Thread.Sleep(1000);
}
}
}

Related

I am running a javafx program and I am getting an IllegalStateException in a situation where I would expect usual Thread interference

tl:dr at the bottom. I am taking a Java course on Udemy and our instructor is demonstrating a situation where background threads can interfere with each other and crash the program. In this case pushing either of the two buttons initiates a method that starts a background Thread, waits, then updates a label. He explains it something along the lines as the threads overwriting each other causing the program to crash with an IllegalStateException. What I don't understand is Threads overwriting each other is not uncommon and just makes the program behave in ways not intended and doesn't usually completely crash the program.
In this case the threads are both trying to change the label to the same String.
Why is this throwing an IllegalStateException instead of just causing the usual interference? After all more than one thread trying to update an object doesn't necessarily crash the program.
tl:dr Why does more than one thread modifying a Label object throw an IllegalStateException in this case but in other multi-threaded programs you just get the usual thread interference? The method of interest is the onButtonClicked() method.
I have tried catching the IllegalStateException to see if I can call Thread.currentThread().getName() but the catch block(both of them actually) seem to get ignored.
public class Controller {
#FXML
private TextField nameField;
#FXML
private Button helloButton;
#FXML
private Button byeButton;
#FXML
private CheckBox ourCheckBox;
#FXML
private Label ourLabel;
#FXML
public void initialize() {
helloButton.setDisable(true);
byeButton.setDisable(true);
}
#FXML
public void onButtonClicked(ActionEvent event) {
if (event.getSource().equals(helloButton)) {
System.out.println("hello, " + nameField.getText());
} else if (event.getSource().equals(byeButton)) {
System.out.println("Bye, " + nameField.getText());
}
Runnable task = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5000);
ourLabel.setText("We did something");
} catch (InterruptedException e) {
System.out.println("Interuppted Exception " + e.getMessage());
} catch (IllegalStateException e) {
System.out.println("Illegal State Exception: " + e.getMessage() + " "
+ Thread.currentThread().getName());
}
}
};
new Thread(task).start();
if (ourCheckBox.isSelected()) {
nameField.clear();
byeButton.setDisable(true);
helloButton.setDisable(true);
}
}
#FXML
public void handleKeyReleased() {
String text = nameField.getText();
boolean disableButtons = text.isEmpty() || text.trim().isEmpty();
byeButton.setDisable(disableButtons);
helloButton.setDisable(disableButtons);
}
#FXML
public void handleChange() {
System.out.println("The checkbox is " +
(ourCheckBox.isSelected() ? "checked" : "not checked"));
}
}
Updating active scene graph elements (such as label text) in your own threads has the potential to cause a race condition (please read and understand the Software section of the link) in the internal state of the JavaFX system. The results of which are unpredictable and a corruption or ”crash” of the JavaFX system cannot be ruled out. Perhaps nothing bad will happen, but perhaps something bad will.
Some calls to JavaFX APIs will detect when potential race condition may occur (when they are being invoked by a thread which is not the JavaFX thread), and fail fast by throwing an IllegalStateException. Other JavaFX APIs may not bother to check the calling thread and may not throw an IllegalStateException, thus allowing the potential race condition to occur. Either way, the users calling code is wrong, it should not be trying to modify the active scene graph off of the JavaFX application thread.
JavaFX code which manipulates the active scene graph (elements or properties of elements currently being displayed in a rendered scene) is only ever expected to occur on a single thread (the JavaFX application thread). In that way a race condition cannot occur.
If you want to feedback information from another thread to the UI, then you can either use the Platform.runLater API, which will execute a piece of code at some time in the future on the JavaFX thread, or make use of utilities in the javafx.concurrent package.

Displaying countdown in multi threaded C# WIndows Forms app

I have tried several solutions with timers (tried all three timer classes) and none fire the Tick(elapsed) event in that specific spot. I have a multi-threaded WinForms application.
What I need seems simple but I have spent days on this and ready to throw in the towel.
I need to display the live countdown in a pop up by second while an action is being executed. If 90 seconds pass with no results achieved (i have a flag), display warning, so I need to update the UI thread for sure.
I have looked into three different Timer classes and none work for me in that particular spot - their elapsed or tick events do not fire. I am thinking it's because I already have another thread that's polling the Serial Port because if I create a dummy button and tie the timer to the Click event, it's fine. Please note that I don't need the Timer to start inside the Serial Port polling, the functionality is totally separate.
Can someone suggest any solution that might work in this case?
Classes i tried are
Windows.Forms.Timer
System.Timers.Timer
System.Threading.Timer
This answer assumes the "Popup" will not blocking the main UI Thread.
Create new MIDI child Form for your "Popup" if you want it to exist within the confines of the parent form otherwise this works fine.
Code taken from Alex's very helpful answer here: How to use a BackgroundWorker?
public Popup()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if(progressBar1.Value == 90)
WarningLbl.Text = "WARNING: Process is taking too long to complete.";
}

IrrKlang Sound Library and Stop Event threads

I have a question about using external c++ library (irrKlang.dll) which is an audio playback engine. Now, the problem is that when I get a SoundStopped event out of it, and do an action in the main form, all kinds of stack related errors arise. Let me show the code:
namespace WindowsFormsApplication4
{
public class IsoundFinished : ISoundStopEventReceiver
{
public delegate void OnSoundStoppedEventHandler(object source, EventArgs e);
public event OnSoundStoppedEventHandler IStopped;
public void OnSoundStopped(ISound iSound, StopEventCause reason, object userData)
{
if (reason.ToString() == "SoundFinishedPlaying")
IStopped?.Invoke(this, EventArgs.Empty);
}
}
}
That is an extended class for me to do custom actions (for example - if sound finished, raise the event...) I am creating an instance of it, for the event action to get exposed in my main Form1 class:
IsoundFinished iStopReceiver = new IsoundFinished();
Now in my main form, I have this line in my Form1() method, just under my InitializeComponent():
iStopReceiver.IStopped += new soundFinished.OnSoundStoppedEventHandler(OnStopped);
It's for subscribing to the event handler. And finally - my OnStopped() method which is supposed to do stuff when the song ends it's playback - it's on the same Form1:
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}
My Stop1 button method is (for those who work with the IrrKlang) ISound.Stop(); and few more lines of code, dealing with the display of playlist and so on. Although I have invoked it from the main UI thread - which should provide me with some degree of thread misalignment protection, all kinds of errors appear, mostly
Cannot evaluate expression because a native frame is on the top of the call stack.
Of course, if I do it without event handler, ISound.Stop(); drops the sound from the engine, like it should. I know something wrong is happening with the threads, but I can't figure out what's going on. If someone would give me few tips, I'd appreciate that a lot.
Well it seems I've solved it myself ! It's all about understanding how the threads are working in Visual C#. The problem was this : I was actually PAUSING the background thread where my audioengine was triggering the event - so 'till I performed an action after INVOKE in the main UI thread, background thread was paused along with the whole irrKlang engine. It was unable to purge itself properly, so it's call stack got clogged!
Using BEGININVOKE solved the problem, as it doesn't PAUSE the background task. It lets it run instead. Diagram on this answer gave me much needed piece of info I was looking for.
Maybe someone will need this answer too, glad I helped myself :P
private void OnStopped(object sender, EventArgs e)
{
if (InvokeRequired)
{
BeginInvoke(new Action<object, EventArgs>(OnStopped), sender, e);
return;
}
btnStop1.PerformClick();
}

Java-ME Application in Freeze Mode

I am developing a Java-ME Based Mobile Application. Now My Requirements are like whenever I am updating one of my RMS, I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen. My Method is already "Synchronized".
Kindly guide me regarding this question.
Thanks.
The best way to handle this is to "serialize" your tasks. You can do this with a message queue - a class that maintains a Vector of message objects (tasks) and runs code based on each message. The queue runs on a thread that processes each task (message) in series. You create a simple message class for the different tasks - read RMS etc. A message can be an Integer if you like that wraps a number. The operation of adding and retrieving messages is synchronized but the code than does the tasks is not and runs on a simple switch block. The benefit of serializing your tasks is you don't have to worry about concurrency. Here is some of the essential code from a class I use to do this.
class MessageQueue implements Runnable{
Vector messages;
Thread myThread;
volatile boolean stop;
public void start() {
stop=false;
myThread=new Thread(this);
myThread.start();
}
// add message to queue - this is public
public synchronized void addMessage(Message m) {
messages.addElement(m);
if(stop) {
start();
} else {
// wake the thread
notify();
}
}
// get next message from queue - used by this thread
private synchronized Message nextMessage() {
if(stop) return null;
if(messages.isEmpty()) {
return null;
} else {
Message m=(Message)messages.firstElement();
messages.removeElementAt(0);
return m;
}
}
public void run() {
while (!stop) {
// make thread wait for messages
if (messages.size() == 0) {
synchronized (this) {
try {
wait();
} catch (Exception e) {
}
}
}
if (stop) {
// catch a call to quit
return;
}
processMessage();
}
}
}
// all the tasks are in here
private void processMessage() {
Message m = nextMessage();
switch (m.getType()) {
case Message.TASK1:
// do stuff
break;
case Message.TASK2:
// do other stuff
break;
case Message.TASK3:
// do other other stuff
break;
default: //handle bad message
}
}
}
What you are asking is very code depended. Usually when you want to make some synchronic actions you just write them one after the other. in java it's more complected, since sometimes you "ask" the system to do something (like repaint() method). But since the RMS read/write operations are very quick (few millisecond) i don't see any need in freesing.
Could you please provide some more information about the need (time for RMS to respond)? does your code runs on system thread (main thread) or your own thread?
I want my application to be stay in a Freeze kind of mode; which means no other action like clicking button or anything else should happen.
First of all I would strongly advise against real freezing of UI - this could make a suicidal user experience for your application.
If you ever happened to sit in front of computer frozen because of some programming bug, you may understand why approach like this is strongly discouraged. As they describe it in MIDP threading tutorial, "user interface freezes, the device appears to be dead, and the user becomes frustrated..."
This tutorial by the way also suggests possibly the simplest solution for problems like you describe: displaying a wait screen. If you don't really have reasons to avoid this solution, just do as tutorial suggests.
To be on a safe side, consider serializing tasks as suggested in another answer. This will ensure that when RMS update starts, there are no other tasks pending.

Is there a prefered approach for introducing a delay before a WCF call

As my user changes the CurrentItem of a dataForm, I need to go the server to get addtional data. It's quite likely that the user could scroll through several items before finding the desired one. I would like to sleep for 500ms before going to get the data.
Is there a component already in the SDK or toolkit like a background worker that would assist in getting back to the UI thread to make my WCF async call once the 500ms sleep is done? It seems that if I don't do that, and try instead to call the WCF async method on the sleeper thread then the Completed event fires on the sleeper thread and not the UI thread, which of course is not good.
I think you might be a little off-track in your thinking. I'm not sure why you feel you need to get back to the UI thread in order to make the asych call. Generally you do as much work as you can on a BG thread and only marshal back to the UI thread when you have the results (by way of the Dispatcher).
I typically use a System.Threading.Timer for this purpose:
public class MyViewModel
{
private readonly Timer refreshTimer;
public MyViewModel()
{
this.refreshTimer = new Timer(this.DoRefresh);
}
public object CurrentItem
{
get { ... }
set
{
...
Invalidate();
}
}
// anything that should invalidate the data should wind up calling this, such as when the user selects a different item
private void Invalidate()
{
// 1 second delay
this.refreshTimer.Change(1000, Timeout.Infinite);
}
private void DoRefresh()
{
// make the async call here, with a callback of DoRefreshComplete
}
private void DoRefreshComplete()
{
// update the UI here by way of the Dispatcher
}
}

Resources