如何从计时器编辑C#中的主窗体?

时间:2015-04-28 15:54:46

标签: c# timer delegates

我正在尝试在表单上显示错误,并使用计时器在一秒钟内删除错误。我有:

const string sendingError = "currently sending a message please wait";
System.Timers.Timer timer = new System.Timers.Timer(1000);
commandValues.errorList[sendingError] = sendingError;
commandValues.updateErrorList();

这可以通过使用错误消息

更新标签来实现
timer.Elapsed += ((source, e) => 
{
    var INDEX = Form.ActiveForm.Controls.IndexOfKey("errorBox");
    Debug.WriteLine(Form.ActiveForm.Controls[INDEX]);
    Form.ActiveForm.Controls[INDEX].Text = "";
    Debug.WriteLine("2" + Form.ActiveForm.Controls[INDEX]);
});

timer.Enabled = true;
timer.Start();

调试行显示

1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
// etcetera

如您所见,第二个调试行永远不会显示。断点同意在我尝试更改标签时离开代表。

我是C#的新手所以任何建议都会受到赞赏,但具体来说我想知道如何在超时后编辑主表单以及为什么我的尝试失败。

2 个答案:

答案 0 :(得分:3)

我不是肯定的我理解你的问题,但听起来你在后台线程中更新UI时遇到了问题?如果是这样,试试这个:

timer.Start()启动一个与Winform的UI线程分开的新线程,因此您可能需要调用WinForm的线程才能看到更改。

timer.Elapsed += ((source, e) =>
{
    var INDEX = Form.ActiveForm.Controls.IndexOfKey("errorBox");
    Debug.WriteLine(Form.ActiveForm.Controls[INDEX]);
    //Invoke the instance of "Form" to process changes on the UI thread
    Form.Invoke((MethodInvoker)delegate
    {
        Form.ActiveForm.Controls[INDEX].Text = "";
    });
    Debug.WriteLine("2" + Form.ActiveForm.Controls[INDEX]);
});
timer.Enabled = true;
timer.Start();

我对调用

的想法

如果WinForm和NOT Data Bound

myControl.Invoke((MethodInvoker) delegate {/*update UI related values here*/});

myForm.Invoke((MethodInvoker) delegate {/*update UI related values here*/});

如果是WinForm和Data Bound,您可能需要通过更新对象的数据绑定属性来更新UI,或者调用数据绑定对象来更新自己的属性(排队 INotifyPropertyChange 或其他类似的接口,将强制刷新UI)。请注意,将代码重构为数据绑定到UI的对象也可以证明是一种永久的解决方案。

如果是XAML \ WPF,您可以使用以下代码段强制从基础应用程序的调度程序更新XPF \ XAML UI,如下所示:

System.Windows.Application.Current.Dispatcher.Invoke((System.Action)delegate {/*update UI related values here*/});

干杯!

答案 1 :(得分:0)

您应该从Timer threadUI Thread发送用户界面修改。不允许从其他线程修改UI元素。

为此,您需要致电this.BeginInvoke

How to update the GUI from another thread in C#?