I am testing my application with mono in anticipation of the Linux port, and I have a threading issue. At first I looked at inserting 3,000 lines of code, but finally I developed a small minimal example;)
You have a form with a button (poetically named Button1 ) and a shortcut (which, without surprise, has the name Label1 )). A whole life is a happy life on a form called Form1 . Clicking Button1 starts an infinite loop that increments the local counter and updates Label1 (using Invoke ) to reflect its value.
Now in Mono, if you change the size of the form, the label stops updating, not restarting. This does not happen with the implementation of MS. BeginInvoke does not work better; Worse, in both cases, the user interface freezes.
Do you know where this discrepancy comes from? How would you decide? And finally, why is BeginInvoke not working here? I have to make a huge mistake ... but what?
EDIT : There is still some progress:
- The BeginInvoke call really works; only the user interface just doesn't update fast enough, so it seems to stop.
- In mono, what happens is that the whole thread hangs when you insert a message into the UI queue (for example, changing the size of the form). In fact, the synchronous
Invoke call never returns. I am trying to understand why. - Interesting: even when using
BeginInvoke asynchronous calls are not made until the resize operation completes. In MS.Net, they continue to work when resized.
The code is as follows (C # version below):
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) { } } }
source share