Я тестирую свое приложение с моно в предвидении порта Linux, и у меня проблема с потоками. Сначала я подумал о том, чтобы вставить сюда 3000 строк кода, но в конце концов придумал небольшой минимальный пример; )
У вас есть форма с кнопкой (поэтическое название Button1
и меткой (которая, что неудивительно, носит имя Label1
)). Все живут счастливой жизнью в форме под названием Form1
. Нажатие на Button1
запускает бесконечный цикл, который увеличивает локальный счетчик и обновляет Label1
(используя Invoke
), чтобы отразить его значение.
Теперь в Mono, если вы измените размер формы, метка перестает обновляться, никогда не перезапускается. Этого не происходит с реализацией MS. BeginInvoke
работает не лучше; Хуже того, в обоих случаях пользовательский интерфейс зависает.
Вы знаете, откуда взялось это несоответствие? Как бы вы ее решили? И наконец, почему здесь не работает BeginInvoke? Я, должно быть, совершаю огромную ошибку ... Некоторый прогресс на данный момент:
Invoke
никогда не возвращается. Я пытаюсь понять, почему. BeginInvoke
асинхронные вызовы не выполняются до завершения операции изменения размера. В MS.Net они продолжают работать при изменении размера. Код выглядит так (версия C # ниже):
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
Или, в 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) {
}
}
}