【问题标题】:System.Timers.Timer not working edit [in asp.net web forms]System.Timers.Timer 不工作编辑 [在 asp.net 网络表单中]
【发布时间】:2015-07-17 14:34:40
【问题描述】:

我正在尝试使用此代码的 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 并且没有增加。

【问题讨论】:

  • 这是在asp.net 应用程序中吗?如果您希望页面动态更改,则需要编写 javascript,而不是代码隐藏中的更多代码

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


【解决方案1】:

正如在其他答案中已经提到的那样,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 的 cmets,他是在网页中执行此操作,而不是像加载事件名称所暗示的那样赢得表单。

如果您不需要来自服务器的任何内容,您可以使用 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;
}

【讨论】:

    【解决方案2】:

    试试这个:

        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 线程上,使其安全。

    【讨论】:

    • 鉴于其他代码在一个名为 Page_Load 的方法中运行,我怀疑这是 asp.net 代码,在这种情况下没有 UI 线程,这里存在更大的问题。
    • 我收到此错误:-“System.Web.UI.WebControls.Label”不包含“Invoke”的定义,并且没有扩展方法“Invoke”接受“System.可以找到 Web.UI.WebControls.Label'(您是否缺少 using 指令或程序集引用?)
    • @SohamBanerjee - 抱歉,我以为这是 Windows 窗体。您需要编写 javascript 来更新网页上的 UI。
    【解决方案3】:

    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();
    }));
    

    【讨论】:

    • "Page_Load" -> 它是 asp.net
    【解决方案4】:

    你可以试试关注,

    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 窗体/Windows 8 应用程序/WP 8(.1) 应用程序不允许从不同线程更改 UI。你需要 UI 线程来更新它。

    【讨论】:

    • 不是c#不允许。不允许这样做的是 Windows 窗体/WPF。
    • 哦...它也不适用于 Windows 8 和 wp 应用程序。所以,基本上我在 c# 中所做的任何事情都不允许我更新 UI。这让我觉得这是处理 UI 的 c# 标准方式。感谢您的认识。相应地更新答案:)
    【解决方案5】:

    尝试使用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();
            }));
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多