DispatcherTimer和Button c#冲突

时间:2014-01-08 21:52:19

标签: c# multithreading xaml windows-phone-8

我是WP8 dev和c#的新手。我正在尝试制作一个在一个间隔内按n计数的循环。我想按一个按钮来增加n。

这是我现在的代码:

namespace Petsounds {
    public partial class MainPage : PhoneApplicationPage {
        float clicks = 0;
        float clickers = 0;
        float clickerBuyers = 0;
        float clickerCost = 5;
        float clickerBuyerCost = 500;
        long savedTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;

        bool buyClickerButtonFlag = false;
        bool clickButtonFlag = false;



        // Constructor
        public MainPage() {
            InitializeComponent();

            //
            DispatcherTimer t = new DispatcherTimer();
            t.Interval = TimeSpan.FromMilliseconds(10);
            t.Tick += (s, e) => startLoop();
            t.Start();

        }

        private void clickButtonOnClick(object sender, RoutedEventArgs e) {
            clickButtonFlag = true;
            System.Diagnostics.Debug.WriteLine("clicked!" + clicks);
        }

        private void buyClickerButtonOnClick(object sender, RoutedEventArgs e) {
            buyClickerButtonFlag = true;
        }

        private void startLoop() {
            if (true) {
                long nowTime = savedTime;
                long timePassed = nowTime - savedTime;

                //user input
                if (clickButtonFlag) {
                    clickButtonFlag = false;
                    clicks++;
                    System.Diagnostics.Debug.WriteLine("clicked!" + clicks);
                }
                if (buyClickerButtonFlag) {
                    buyClickerButtonFlag = false;
                    if (clicks > clickerCost) {
                        clickers++;
                        clicks -= clickerCost;
                        clickerCost *= 1.6F;
                    }
                    System.Diagnostics.Debug.WriteLine("clicker bought!" + clickers);
                }
                //update vars
                if (timePassed > TimeSpan.TicksPerSecond) {
                    savedTime = nowTime;
                    nowTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;

                    clicks += clickers;
                }

                //update display
                clickCount.Text = clicks.ToString();
                buyClickerButtonCost.Text = "Cossst " + clickerCost.ToString();
            }
        }
    }
}

我的按钮不一致,如果删除线程,按钮会响应(但当然计数器不起作用。)

编辑:

我已经改变了

DispatcherTimer t = new DispatcherTimer();
t.Interval = TimeSpan.FromMilliseconds(10);
t.Tick += (s, e) => startLoop();
t.Start();

Timer myTimer = new Timer(startLoop);
myTimer.Change(1000, 10);

现在出现错误:

A first chance exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll

在线

clickCount.Text = clicks.ToString();

3 个答案:

答案 0 :(得分:1)

首先......你会很快发现10ms不是10ms ......它甚至可能不是那么接近......如果你做1000ms ..那将是更准确的。

此外,DispatcherTimer将每个时间间隔对GUI线程的函数调用进行排队...这意味着您正在使用startLoop()调用充斥GUI线程。这不会让线程有更多的时间来更新其他任何内容......就像你的按钮一样。

答案 1 :(得分:0)

就像@Andrew说的那样--DispatcherTimer适用于UI线程,并且通过如此小的intervall阻止它。
如果你想要这么小的间隔,你可以在不同的线程上使用Timer:

public MainPage()
{
   InitializeComponent();

   System.Threading.Timer myTimer = new Timer(MyTimerCallback);
   myTimer.Change(1000, 10);
}
private static int value = 0;

private static void MyTimerCallback(object state)
{
   value++;
}

但是你必须记住你在不同的线程上使用它 - 这个Timer无法访问你的UI元素(按钮等)。

修改

你说服我检查一下:

    static float clicks = 0;
    static float clickers = 0;
    static float clickerCost = 5;
    static long savedTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;

    static bool buyClickerButtonFlag = false;
    static bool clickButtonFlag = false;

    public MainPage()
    {
        InitializeComponent();

        first.Click += ShowCounter;

        DispatcherTimer t = new DispatcherTimer();
        t.Interval = TimeSpan.FromSeconds(5);
        t.Tick += ShowCounter;
        t.Start();

        System.Threading.Timer myTimer = new Timer(MyTimerCallback);
        myTimer.Change(10, 10);
    }

    private void ShowCounter(object sender, EventArgs e)
    {
        textBlck.Text = clicks.ToString();
    }

    private static void MyTimerCallback(object state)
    {
        clicks++; // added to check running
        if (true)
        {
            long nowTime = savedTime;
            long timePassed = nowTime - savedTime;

            //user input
            if (clickButtonFlag)
            {
                clickButtonFlag = false;
                clicks++;
                System.Diagnostics.Debug.WriteLine("clicked!" + clicks);
            }
            if (buyClickerButtonFlag)
            {
                buyClickerButtonFlag = false;
                if (clicks > clickerCost)
                {
                    clickers++;
                    clicks -= clickerCost;
                    clickerCost *= 1.6F;
                }
                System.Diagnostics.Debug.WriteLine("clicker bought!" + clickers);
            }
            //update vars
            if (timePassed > TimeSpan.TicksPerSecond)
            {
                savedTime = nowTime;
                nowTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;
                clicks += clickers;
            }
        }
    }

我在设备上进行了测试,按钮正常工作。

另一方面 - 当你可以轻松地将工作放到按钮点击事件时,放置一个等待标志按钮的方法是什么意思。当用户点击按钮时发生这种情况 - 不要一直检查按钮状态。

答案 2 :(得分:0)

您可能需要考虑不同的方法。

如果您的任务是在用户触摸按钮时增加数值(并且数字以稳定的速度增加),请考虑使用RepeatButton。

RepeatButton:表示一个控件,从按下它直到它被释放的时候反复引发它的Click事件。

<强> XAML

 <!-- 
   Delay: The time, in milliseconds, the RepeatButton waits 
          when it is pressed before it starts repeating the click action.

  Interval: The time, in milliseconds, between repetitions 
            of the click action, as soon as repeating starts.
  -->
  <RepeatButton Content='Buy'
                Interval='50' Delay='100' 
                Click='RepeatButton_Click' />

<强>代码

private float buyCounter = 0;
private void RepeatButton_Click(object sender, RoutedEventArgs e) {
  buyCounter += 1;
  buyClickerButtonCost.Text = buyCounter.ToString();
}