PIC*_*ain 12 .net c# controls refresh
我有一个带有statusLabel的Windows窗体(C#.NET),我似乎无法在事件处理程序方法的过程中更新.我的代码看起来像这样......
void Process_Completed(object sender, EventArgs e)
{
string t = "Process is finished!";
this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
}
void Process_Started(object sender, EventArgs e)
{
string t = "Process has begun";
this.Invoke(new StatusLabelUpdator(updateStatusLabel), new object[] { t });
}
private delegate void StatusLabelUpdator(string text);
private void updateStatusLabel(string text)
{
StatusLabel1.Text = text;
statusStrip1.Invalidate();
statusStrip1.Refresh();
statusStrip1.Update();
}
Run Code Online (Sandbox Code Playgroud)
当我运行代码时,一旦进程启动,就会触发Process_Started方法,几秒钟后会触发Process_Completed方法.由于某种原因,我不能让状态标签显示"过程已经开始".它只显示"过程完成!".正如您所看到的,我已尝试使包含状态标签但未成功的状态条无效,刷新和更新.我无法在statuslabel本身上调用update/refresh/invalidate,因为这些方法不可用.我究竟做错了什么?
添加信息:
通过单击窗体上的按钮启动"进程",该窗体在单独的类中调用方法,如下所示:
public void DoSomeProcess()
{
TriggerProcessStarted();
System.Threading.Thread.Sleep(2000); // For testing..
TriggerProcessComplete();
}
Run Code Online (Sandbox Code Playgroud)
在TriggerProcessxxxx方法中,我使用此代码触发事件...
var EventListeners = EH.GetInvocationList(); //EH is the appropriate EventHandler
if (EventListeners != null)
{
for (int index = 0; index < EventListeners.Count(); index++)
{
var methodToInvoke = (EventHandler)EventListeners[index];
methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, new object[] { });
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我已添加Application.DoEvents()到该updateStatusLabel方法但它没有帮助.我仍然得到相同的结果.这是我的更新方法.
private void updateStatusLabel(string text)
{
StatusLabel1.Text = text;
statusStrip1.Refresh();
Application.DoEvents();
}
Run Code Online (Sandbox Code Playgroud)
所以我猜测"处理"是在UI线程上进行的,但是事件处理程序在它自己的线程上调用,然后在UI线程上调用控件更新.这是一种愚蠢的做事方式吗?注意:包含DoSomeProcess()方法的类位于我引用的单独的.NET ClassLibrary中.
T.J*_*der 17
如果您正在UI线程上进行处理,则在处理运行时,它将无法执行任何其他操作(如重绘更新的标签).因此,例如,如果处理发生是因为用户单击按钮并由按钮单击处理程序触发(没有明确地将其放在另一个线程上),则它正在UI线程上运行.即使您更新了标签的文本,它也会在收到绘制消息之前被绘制,此时它可能正在忙于处理.
答案是在单独的线程上进行长时间运行的处理.hack(恕我直言)Application.DoEvents用于让UI线程在处理过程中执行一些UI操作.如果您在更新标签之后和开始处理之前放置其中一个,那么标签将重新粉刷的可能性非常高.但是,在处理过程中,没有其他绘制事件可以被处理(当有人在应用程序上移动另一个应用程序窗口并返回时,导致半绘制窗口等).因此,我称之为黑客(即使,呃,嗯,我已经知道这样做了:-)).
根据您的修改编辑更新:
回覆
所以我猜"处理"是在UI线程上发生的,但是事件处理程序是在它自己的线程上调用的......
我假设DoSomeProcess是从UI线程触发的(例如,直接响应按钮点击或类似).如果是这样,那么是的,你的处理绝对是在UI线程上.因为通过异步TriggerProcessStarted触发你的回调,你不知道它什么时候会运行,但无论如何你的代码会立即启动进入处理,永不屈服,所以没有其他人能够抓住那个线程.由于这是UI线程,对委托的调用将阻止调用设置标签的文本,因此它必须等待UI线程(忙于处理).(并且假设它安排在不同的线程上;我无法100%说服自己,因为微软有两个不同的 - 其中一个设计师承认的IIRC是一个真正愚蠢的想法 - 而且它已经有一段时间了因为我和这些东西打架过.)BeginInvokeInvokeBeginInvoke
如果你TriggerProcessStarted同步调用你的回调,你应该没问题.但理想情况下,在自己的线程上安排处理(如果它不是UI).
| 归档时间: |
|
| 查看次数: |
25407 次 |
| 最近记录: |