很抱歉,如果有人提出这个要求。我找不到这个问题的具体答案,被困住了。我正在学习定时器。我是VBA程序员,并且涉足C#。
我正在尝试编写一个跨平台的应用程序,但是myTimer.Elapsed事件遇到了无法正常执行的更新标签的问题。
我已阅读Goalkicker.com的C#专业版注释中的计时器一章,并尝试复制其倒数计时器。我也阅读了Timer.Elapsed事件的Microsoft API。都没有给我关于我要去哪里错误的明确答案。 Google也不太友善,因为我可能查询不正确。
我试图停止计时器,只是允许该方法运行,直接在我的Elapsed方法中写入标签,并在一个单独的方法中更新标签(如代码所示)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading;
using System.Timers;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Essentials;
using Plugin.Geolocator;
namespace LocationServices
{
public partial class MainPage : ContentPage
{
public int timeLeft = 3;
public Timer myTimer = new Timer();
SensorSpeed speed = SensorSpeed.UI; //ignore
public MainPage()
{
InitializeComponent();
cmdGetLocation.Clicked += GetLocation; //ignore
cmdStartTimer.Clicked += StartTimer;
Accelerometer.ReadingChanged += MainPage_ReadingChanged; //ignore
InitializeTimer();
}
private void UpdateTimeLeftLabel(string NumberToDisplay)
{
txtTimeRemaining.Text = "Time left: " + NumberToDisplay;
}
private void InitializeTimer()
{
myTimer.Interval = 1000;
myTimer.Enabled = true;
myTimer.Elapsed += MyTimer_Elapsed;
UpdateTimeLeftLabel(timeLeft.ToString()); //working just fine
}
private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)
{
myTimer.Stop();
UpdateTimeLeftLabel(timeLeft.ToString()); //this one is not working.
if (timeLeft <= 0)
{
myTimer.Dispose();
}
else
{
timeLeft -= 1;
myTimer.Start();
}
}
private void StartTimer(object sender, EventArgs e)
{
myTimer.Start();
}
}
}
我的计时器事件正在触发,因为按预期达到了断点。正如在即时窗口中已验证的那样,正在调整timeLeft变量。只是标签没有更新。
答案 0 :(得分:1)
使用BeginInvokeOnMainThread
强制您的UI代码在UI线程上运行
private void UpdateTimeLeftLabel(string NumberToDisplay)
{
Device.BeginInvokeOnMainThread( () => {
txtTimeRemaining.Text = "Time left: " + NumberToDisplay;
});
}
答案 1 :(得分:0)
只需在此处添加更多信息作为支持信息
.NET包含四个名为Timer的类,每个类提供不同的功能:
System.Timers.Timer
,它会定期触发一个事件并在一个或多个事件接收器中执行代码。该类旨在在多线程环境中用作基于服务器的组件或服务组件。它没有用户界面,并且在运行时不可见。System.Threading.Timer
,它定期在线程池线程上执行一个回调方法。回调方法是在实例化计时器且无法更改时定义的。与System.Timers.Timer类类似,该类旨在用作多线程环境中的基于服务器或服务的组件。它没有用户界面,并且在运行时不可见。System.Windows.Forms.Timer
(仅.NET Framework),这是一个Windows Forms组件,它会定期触发一个事件并在一个或多个事件接收器中执行代码。该组件没有用户界面,并且设计用于单线程环境。它在UI线程上执行。System.Web.UI.Timer
(仅.NET Framework),一个ASP.NET组件,该组件定期执行异步或同步网页回发。现在,您的问题是您最有可能使用线程计时器。这意味着您需要Marshall返回到 UI线程,因为您无法从另一个线程更新 UI 。
请参阅杰森斯的答案