计时器调度在WP7上无序更改

时间:2012-07-16 22:17:39

标签: c# windows-phone-7 timer begininvoke dispatch

我正在尝试在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等)

感谢您的任何建议。

3 个答案:

答案 0 :(得分:0)

您应该使用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();
    }
}

答案 1 :(得分:0)

尝试以下mod:

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,以获得更高的准确性(一切都已在上面实现)。希望有所帮助。

答案 2 :(得分:0)

查看代码和注释时,我怀疑你的应用程序的错误不是使用Timer代码,而是使用任何初始化Timer - 我怀疑定时器正在被构造两次。

如果没有看到你发布的块之外的代码就很难调试它,但你描述的症状表明你正在初始化多个Timers和多个堆栈/闭包变量oldTimenewTime

在简单的层面上,您可以尝试保护定时器结构 - 例如有类似的东西:

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