我正试图在Windows Phone 7上制作一个倒计时计时器,这对我的应用程序非常重要。但我找不到任何方法来每隔一秒更新UI规则中的文本。
Timer dt = new System.Threading.Timer(delegate
{
Dispatcher.BeginInvoke(() =>
{
newtime = oldtime--;
System.Diagnostics.Debug.WriteLine("#" + counter.ToString() +
" new: " + newtime.ToString() +
" old: " + oldtime.ToString());
counter++;
oldtime = newtime;
}
}, null, 0, 1000);
运行我的应用程序控制台后,输出似乎是这样的:
#1 new: 445 old: 446 #2 new: 444 old: 445 #3 new: 445 old: 446 #4 new: 443 old: 444 #5 new: 444 old: 445 #6 new: 442 old: 443 #7 new: 443 old: 444 #8 new: 441 old: 442
我不知道如何摆脱那些不需要的调用(#3、#5、#7等)
谢谢你的建议。
您应该使用DispatcherTimer。以下示例显示了一个计时器从十开始倒计时。
DispatcherTimer _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
int _timeLeft = 10;
public MyClass()
{
InitializeComponent();
_timer.Tick += TimerTick;
_timer.Start();
MyTextBox.Text = _timeLeft.ToString();
}
void TimerTick(object sender, EventArgs e)
{
_timeLeft--;
if (_timeLeft == 0)
{
_timer.Stop();
MyTextBox.Text = null;
}
else
{
MyTextBox.Text = _timeLeft.ToString();
}
}
尝试以下模式:
DispatcherTimer _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
int _timeLeft = 50;
Stopwatch watch = new Stopwatch();
public MainPage()
{
InitializeComponent();
_timer.Tick += TimerTick;
_timer.Start();
textBlock1.Text = _timeLeft.ToString();
watch.Start();
}
void TimerTick(object sender, EventArgs e)
{
if ((_timeLeft - (int)watch.Elapsed.TotalSeconds) <= 0)
{
watch.Stop();
_timer.Stop();
textBlock1.Text = null;
}
else
{
textBlock1.Text = (_timeLeft - (int)watch.Elapsed.TotalSeconds).ToString();
}
}
顺便说一句,Shawn的代码在我的设备上运行得很好,但如果你遇到问题,只需使用Stopwatch
并从时间变量中减去经过的时间。此外,运行DispatcherTimer
的速度要快一点(当然对于这种技术),比如200ms,以获得更高的精度(上面已经实现了所有内容)。希望能有所帮助。
查看代码和注释,我怀疑应用程序的错误不是Timer代码,而是初始化Timer的原因——我怀疑定时器被构造了两次。
如果没有看到您发布的块之外的代码,很难对此进行调试,但您描述的症状表明您正在初始化多个定时器和多个堆栈/闭包变量oldTime
和newTime
在一个简单的层面上,你可以尝试保护定时器结构,例如:
public class MyClass
{
// existing code...
private bool _timerStarted;
private void StartTimer()
{
if (_timerStarted)
{
Debug.WriteLine("Timer already started - ignoring");
return;
}
_timerStarted = true;
var newTime = 500;
var oldTime = 500;
var counter = 1;
Timer dt = new System.Threading.Timer(delegate
{
Dispatcher.BeginInvoke(() =>
{
newtime = oldtime--;
System.Diagnostics.Debug.WriteLine("#" + counter.ToString() +
" new: " + newtime.ToString() +
" old: " + oldtime.ToString());
counter++;
oldtime = newtime;
}
}, null, 0, 1000);
}
}