System.Timers.Timer不工作编辑[在asp.net网络表单]

时间:2015-05-07 06:57:39

标签: c# asp.net system.timers.timer

我正在使用以下代码尝试Timer类: -

protected void Page_Load(object sender, EventArgs e)
{
    System.Timers.Timer tm = new System.Timers.Timer();
    tm.Elapsed += new System.Timers.ElapsedEventHandler(tm_Elapsed);
    tm.Interval = 1000;
    tm.Start();
}

void tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    int lbl = Convert.ToInt32(Label1.Text);
    Label1.Text = (lbl+1).ToString();
}

最初,Label1.Text是" 1"。

但是当我运行该应用程序时,标签的文字显示为1并且不会增加。

5 个答案:

答案 0 :(得分:2)

正如其他答案中已经提到的那样,System.Timers.Timer在非GUI线程上被触发。这不会允许您访问GUI元素并会引发跨线程异常。您可以使用MethodInvoker访问tm_Elapsed事件中的GUI元素。由于您在表单中有Timer并且想要访问GUI元素,因此其他Timer类最适合您System.Windows.Forms.Timer

  

实现以用户定义的间隔引发事件的计时器。   此计时器已针对Windows窗体应用程序进行了优化,并且必须   在窗口中使用。

protected void Page_Load(object sender, EventArgs e)
{         
     System.Windows.Forms.Timer tm = new System.Windows.Forms.Timer();
     tm.Tick += tm_Tick;
     tm.Interval = 1000;
     tm.Start();
}

void tm_Tick(object sender, EventArgs e)
{
     int lbl = Convert.ToInt32(label1.Text);
     label1.Text = (lbl + 1).ToString();
}
根据OP的评论

编辑,他正在网页中执行此操作,而不是加载事件名称所示的表单。

如果您不需要任何服务器,可以使用javascript。如果您想更新html控件并需要从服务器执行,那么您可以使用asp:Timer

Html(.aspx)

  <form id="form1" runat="server">             
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <asp:Timer runat="server" id="UpdateTimer" interval="5000" ontick="UpdateTimer_Tick" />
        <asp:UpdatePanel runat="server" id="TimedPanel" updatemode="Conditional">
            <Triggers>
                <asp:AsyncPostBackTrigger controlid="UpdateTimer" eventname="Tick" />
            </Triggers>
            <ContentTemplate>
                 <asp:Label id="Label1" runat="server" Text="1" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>

背后的代码

protected void UpdateTimer_Tick(object sender, EventArgs e)
{
    Label1.Text = int.Parse(Label1.Text) + 1;
}

答案 1 :(得分:1)

试试这个:

    void tm_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Label1.Invoke((Action)(() =>
        {
            int lbl = Convert.ToInt32(Label1.Text);
            Label1.Text = (lbl+1).ToString();
        }));
    }

问题是System.Timers.Timer在非UI线程中触发其事件,并且由于您无法从非UI线程安全地访问或更新控件,因此它似乎不起作用。

在UI元素上调用.Invoke(...)允许您将代码推送到UI线程,使其安全。

答案 2 :(得分:1)

System.Timers.Timer旨在用于多线程环境。您不能直接访问Elapsed事件中的ui元素。

如果您的应用程序是Windows窗体,请使用System.Windows.Forms.Timer。 如果您的应用程序是WPF,请使用System.Windows.Threading.DispatcherTimer。

如果出于任何原因想要使用System.Timers.Timer,请使用ui元素的Invoke方法。例如,在Windows窗体中:

Label1.Invoke(new Action(() =>
{
    int lbl = Convert.ToInt32(Label1.Text);
    Label1.Text = (lbl+1).ToString();
}));

答案 3 :(得分:0)

您可以尝试以下,

if(this.Label1.InvokeRequired)
     {
         this.Label1.BeginInVoke((MethodInvoker) delegate() { int lbl = Convert.ToInt32(Label1.Text);
Label1.Text = (lbl+1).ToString();});    
     }
     else
     {
         int lbl = Convert.ToInt32(Label1.Text);
         Label1.Text = (lbl+1).ToString();
     }

问题是,WPF / Windows Forms / Windows 8 app / WP 8(.1)应用程序不允许从不同的线程更改UI。您需要UI线程来更新它。

答案 4 :(得分:0)

尝试将System.Threading.Timer(线程安全)与@Enigmativity解决方案结合使用以避免跨线程异常:

    private System.Threading.Timer m_timer = null;
    private const int DUE_TIME = 1000;
    private const int INTERVAL = 1000;

    private void Page_Load(object sender, EventArgs e)
    {
        System.Threading.AutoResetEvent autoEvent = new System.Threading.AutoResetEvent(false);
        System.Threading.TimerCallback tcb = new System.Threading.TimerCallback(timer_Elapsed);
        m_timer = new System.Threading.Timer(tcb, null, DUE_TIME, INTERVAL);
    }

    void timer_Elapsed(object sender)
    {
        label1.Invoke((Action)(() =>
        {
            int lbl = Convert.ToInt32(label1.Text);
            label1.Text = (lbl + 1).ToString();
        }));
    }