C# 为什么不是';“我的活动”;myTimer\u在更新设备上的标签时超时?

C# 为什么不是';“我的活动”;myTimer\u在更新设备上的标签时超时?,c#,xamarin.forms,cross-platform,visual-studio-2019,system.timers.timer,C#,Xamarin.forms,Cross Platform,Visual Studio 2019,System.timers.timer,如果有人问这个问题,我很抱歉。我找不到这个问题的具体答案,我被卡住了。我现在正在学习计时器。我是一名VBA程序员,涉猎过C 我正在尝试编写一个跨平台的应用程序,但我的myTimer.Appeased事件在更新标签时遇到了问题 我在goalkicker.com上读过《C#Notes for Professionals》中的计时器一章,并尝试复制他们的倒计时计时器。我还阅读了Timer.Appeased事件的Microsoft API。他们都没有给我一个明确的答案,说明我错在哪里。谷歌也不太友善,因

如果有人问这个问题,我很抱歉。我找不到这个问题的具体答案,我被卡住了。我现在正在学习计时器。我是一名VBA程序员,涉猎过C

我正在尝试编写一个跨平台的应用程序,但我的myTimer.Appeased事件在更新标签时遇到了问题

我在goalkicker.com上读过《C#Notes for Professionals》中的计时器一章,并尝试复制他们的倒计时计时器。我还阅读了Timer.Appeased事件的Microsoft API。他们都没有给我一个明确的答案,说明我错在哪里。谷歌也不太友善,因为我可能查询不正确

我已经尝试停止计时器,只允许该方法运行,直接在已用方法中写入标签,并在单独的方法中更新标签(如代码所示)

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
//使用系统线程;
使用系统计时器;
使用System.Threading.Tasks;
使用Xamarin.Forms;
使用Xamarin.Essentials;
使用Plugin.geologitor;
命名空间位置服务
{
公共部分类主页:ContentPage
{
公共int timeLeft=3;
公共计时器myTimer=新计时器();
SensorSpeed速度=SensorSpeed.UI;//忽略
公共主页()
{
初始化组件();
cmdGetLocation.Clicked+=GetLocation;//忽略
cmdStartTimer.Clicked+=StartTimer;
Accelerator.ReadingChanged+=主页面\u ReadingChanged;//忽略
初始化对象();
}
私有void UpdateTimeLeftLabel(字符串编号显示)
{
txtTimeLeving.Text=“剩余时间:”+数字显示;
}
私有void初始化项()
{
myTimer.Interval=1000;
myTimer.Enabled=true;
myTimer.appeased+=myTimer\u appeased;
UpdateTimeLeftLabel(timeLeft.ToString());//工作正常
}
私有void MyTimer_已过(对象发送方,ElapsedEventArgs e)
{
myTimer.Stop();
UpdateTimeLeftLabel(timeLeft.ToString());//这一个不起作用。

如果(timeLeft使用
BeginInvokeMainThread
强制UI代码在UI线程上运行

private void UpdateTimeLeftLabel(string NumberToDisplay)
    {
        Device.BeginInvokeOnMainThread( () => {
          txtTimeRemaining.Text = "Time left: " + NumberToDisplay;
        });
    }

只需在此处添加更多信息作为支持信息

.NET包括四个名为Timer的类,每个类提供不同的功能:

  • System.Timers.Timer
    ,它触发事件并定期在一个或多个事件接收器中执行代码。该类旨在用作多线程环境中基于服务器的组件或服务组件;它没有用户界面,在运行时不可见
  • System.Threading.Timer
    ,它定期在线程池线程上执行单个回调方法。回调方法是在实例化计时器时定义的,不能更改。与System.Timers.Timer类类似,此类旨在用作多线程环境中基于服务器的组件或服务组件;它没有用户界面,在运行时不可见
  • System.Windows.Forms.Timer
    (仅限.NET Framework),一种Windows窗体组件,用于触发事件并定期在一个或多个事件接收器中执行代码。该组件没有用户界面,设计用于单线程环境;它在UI线程上执行
  • System.Web.UI.Timer
    (仅限.NET Framework),一种ASP.NET组件,以固定间隔执行异步或同步网页回发
现在的问题是,您很可能正在使用线程计时器。这意味着您需要返回到UI线程,因为您无法从另一个线程更新UI


请参见Jasons的答案

哦!我还更改了me StartTimer方法,以直接更改标签,而不实际调用myTimer.Start()这成功地更新了我希望更新的标签。所以,你可以回答你自己的问题。Jason,这很有效。我很欣赏这个解决方案。但是我哪里出了问题?是不是我对线程不太精通?我理解线程的概念和什么是多线程,但我似乎无法完全理解线程n use yet.UI更新只能从主UI线程完成。您正在使用的计时器在后台线程上启动。BeginInvokeMainThread只是强制您的代码在UI线程上运行,以便它可以更新UI。因此,这是关于我对线程的理解不足。今晚我将深入研究这本C#书。谢谢你们两位!)
private void UpdateTimeLeftLabel(string NumberToDisplay)
    {
        Device.BeginInvokeOnMainThread( () => {
          txtTimeRemaining.Text = "Time left: " + NumberToDisplay;
        });
    }