【发布时间】:2014-03-17 06:41:16
【问题描述】:
我是一名新手编码员,如果这听起来像一个愚蠢的问题,请原谅。我已经检查了 SO 并搜索了一个很好的解释,以很好地解释如何从另一个线程/类更新表单的控件(即列表视图、标签)而不冻结表单并且不将表单暴露给其他类(也就是订阅事件)。我还没有找到任何可以解决我的问题或得到彻底解释的东西。
这是我目前所拥有的,但 UI 在更新时仍然冻结...
public partial class Main : Form
{
private void Main_Load(object sender, EventArgs e)
{
UIEvents.CounterChanged += UpdateCounterLabel;
}
public void UpdateCounterLabel(string text)
{
lock (lblCounter)
{
try
{
if (lblCounter.InvokeRequired)
lblCounter.Invoke((MethodInvoker)(() => lblCounter.Text = string.Format("[{0}]", text)));
else
lblCounter.Text = string.Format("[{0}]", text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
DoWork() 是从第二个线程调用的:
public static class UIEvents
{
public static event UpdateCounterHandler CounterChanged;
public delegate void UpdateCounterHandler(string text);
public static void UpdateCounter(string text)
{
if (CounterChanged != null)
CounterChanged(text);
}
}
public static class Worker
{
public static void DoWork()
{
int result;
...
..
.
UIEvents.UpdateCounter(result.ToString());
}
}
那么我哪里错了?
【问题讨论】:
-
你每秒调用多少次
UpdateCounterLabel?也许,你应该扼杀它。另外,如果可以的话,使用BeginInvoke而不是Invoke。 -
每秒调用多次(可能 10-20 次,具体取决于线程数)。我从未使用过 BeginInvoke……它比 Invoke 有什么好处?
-
有人吗?即使你能指出一个好的教程的方向,也没关系。
-
我敢打赌,您在工作线程的紧密循环中调用
Invoke,从而阻塞 UI 线程消息循环。试试BegingInvoke,它是异步的,在你的工作线程中使用Stopwatch每秒更新UI 不超过24 次。无论如何,用户的眼睛将无法跟踪更频繁的更新。
标签: c# .net multithreading winforms