单声道挂起且MS.Net不会出现的线程问题 [英] A threading problem where mono hangs and MS.Net doesn't
问题描述
我正在预配置Linux端口时用mono测试我的应用程序,但是我遇到了线程问题.我最初考虑在此处粘贴3000条代码行,但最终我设计了一个小小的示例;)
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 ;)
您有一个带有按钮的窗体(通常命名为Button1
)和标签(带有标签(毫无疑问地带有名称Label1
)).整个过程都以称为Form1
的形式过着幸福的生活.单击Button1
将启动无限循环,该循环将递增本地计数器并更新Label1
(使用Invoke
)以反映其值.
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.
现在在Mono中,如果您调整窗体的大小,标签将停止更新,永远不会重新启动. MS实施不会发生这种情况. BeginInvoke
不能更好地工作;更糟糕的是,这两种情况都会使UI挂起.
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.
您知道这种差异来自何处吗?您将如何解决?最后,为什么BeginInvoke在这里不起作用?我一定是犯了个大错误...但是哪个呢?
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:
- 实际上,调用BeginInvoke确实可以;只是,UI的刷新速度不够快,因此似乎停止了.
- 在mono上,发生的事情是当您在UI队列中插入一条消息时整个线程挂起(例如,通过调整表单大小).实际上,同步
Invoke
调用永不返回.我正试图了解原因. - 有趣的是:即使使用
BeginInvoke
,在调整大小操作结束之前,异步调用也不会执行.在MS.Net上,它们在调整大小的同时保持运行.
- 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.
代码看起来像这样(C#版本较低):
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
或者,在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) {
}
}
}
推荐答案
这是mono运行时中的错误,至少我认为是.代码可能不是一个好习惯(我不是线程专家),但是提示错误的原因是Windows和Linux上的行为不同.
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.
在Linux上,mono具有与Windows上的MS.Net完全相同的行为.调整大小时不会挂起,也不会持续更新.
On Linux, mono has exactly the same behaviour as MS.Net has on windows. No hanging, continuous updates even while resizing.
在Windows上,mono显示所有上述问题.我已经在 https://bugzilla.novell.com/show_bug.cgi?id=690400 <上发布了一个错误报告. /a>.
On Windows, mono displays all the aforementioned problems. I've posted a bug report at https://bugzilla.novell.com/show_bug.cgi?id=690400 .
这篇关于单声道挂起且MS.Net不会出现的线程问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!