多线程问题

时间:2011-07-07 12:16:35

标签: c# winforms multithreading invoke

我正在使用计时器来重置我用作警告框的标签。基本上,如果用户做了某些事情(更具体地说,出现了问题,例如:他使用了程序无法识别的单词),这会及早发现错误,并将发生的事情告诉他,以便他可以更改输入。

重置在5秒后消隐标签,以防止他看到“请不要使用中文字符”之类的内容,并且可能仍然认为旧的错误仍然存​​在。这是我读取调用的内容(因为我听说b​​egininvoke需要endinvoke,我选择了调用)。

private void lblWrn_TextChange(object sender, EventArgs e)
{
    Timee = new System.Timers.Timer(5000);
    Timee.Elapsed += new ElapsedEventHandler(timerClearWrn);
    Timee.Enabled = true;
}

string empty = "";
private void timerClearWrn(object sender, ElapsedEventArgs elapsed)
{
    lblWrn.Invoke(new Action<Label>(lblWrn), new object[] { lblWrn, "" });
}

我不太确定我在哪里出错,并查找示例,无法确定要更改的部分。有人可以向我解释错误或调用更多吗?

4 个答案:

答案 0 :(得分:2)

如果是Windows窗体应用程序,请使用System.Windows.Forms.Timer,然后不需要调用,因为在主线程上执行定时器回调。

此外,不要在每次文本更改时创建新的计时器。

答案 1 :(得分:2)

实际上,Control.BeginInvoke 需要EndInvoke;它是 Delegate.BeginInvoke

首先,我还建议使用Windows.Forms.Timer,因为看起来你正在使用winforms - 它将自动触发UI线程,使所有问题都消失 - 只需运行代码你想在处理程序中运行(不要使用Invoke等)

示例中的问题是参数不匹配; Action<>期望调用方法名称(更准确地说:方法组),并且数组中的参数必须合适。由于您没有显示您计划调用的方法,我无法帮助 - 但lblWarn不是方法(它是一个字段)。

答案 2 :(得分:1)

就行了 lblWrn.Invoke(新动作( lblWrn ),新对象[] {lblWrn,&#34;&#34;});

粗体部分不应该是一个功能而不是一个对象吗?

答案 3 :(得分:0)

您有几个选择。选项1有点笨重。选项2和3更好。

选项1:继续使用Control.Invoke的一般策略,但使用正确调用Invoke的代码,禁用自动重置计时器,并删除事件处理程序。< / p>

private void lblWrn_TextChange(object sender, EventArgs e)
{
    var Timee = new System.Timers.Timer(5000);
    Timee.Elapsed += this.timerClearWrn;
    Timee.AutoReset = false; // Raise the Elapsed event only once
    Timee.Enabled = true;
}

private void timerClearWrn(object sender, ElapsedEventArgs elapsed)
{
    lblWrn.Invoke(
      (MethodInvoker)(()=>
      {
        lblWrn.Text = "";
      }), null);
    var Timee = (System.Timers.Timer)sender;
    Timee.Elapsed -= this.timerClearWrn;
}

选项2:使用System.Windows.Forms.Timer代替System.Timers.Timer

选项3 :使用SynchronizingObject的{​​{1}}属性。当从UI线程动态创建和使用定时器时,这是我的首选选项。

System.Timers.Timer