WPF 实现抽奖机

2019-04-23  本文已影响0人  Memoyu

认知尚浅,如有错误,愿闻其详!

概述

近期学习到了线程,有个作业就是做一个滚动抽奖机,实现的过程中也遇到了一些问题,总结一下。
而且仍然存在着一个问题,就是问题出在线程休眠,导致获取到的随机奖号List集合与label上显示的可能不一致。有点愚钝,没找到解决方法。


踩的坑



代码

XAML
<Window x:Class="摇奖机.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:摇奖机"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="600" WindowStartupLocation="CenterScreen">
    <StackPanel>
        <Label FontSize="20" Height="40" Margin="20" HorizontalContentAlignment="Center">
            抽奖机
        </Label>
        <DockPanel Height="50" Name="panel" >
            
            <Label Name="num_1" Width="100" FontSize="20" Margin="10" HorizontalContentAlignment="Center" >
                0
            </Label>
            <Label Name="num_2" Width="100" FontSize="20" Margin="10" HorizontalContentAlignment="Center" >
                0
            </Label>
            <Label Name="num_3" Width="100" FontSize="20" Margin="10" HorizontalContentAlignment="Center" >
                0
            </Label>
            <Label Name="num_4" Width="100" FontSize="20" Margin="10" HorizontalContentAlignment="Center" >
                0
            </Label>
            <Label Name="num_5" Width="100" FontSize="20" Margin="10" HorizontalContentAlignment="Center" >
                0
            </Label>
        </DockPanel>

        <Button Name="btnStart" Content="开始" Height="40" Width="200" Margin="30"></Button>
        <DockPanel HorizontalAlignment="Center">
            <Label FontSize="18" HorizontalContentAlignment="Center">本回抽出的数为:</Label>
            <Label Name="currentLuckNumLabel" FontSize="18" HorizontalContentAlignment="Center"></Label>
        </DockPanel>

        <DockPanel HorizontalAlignment="Center">
            <Label FontSize="18" HorizontalContentAlignment="Center">上回抽出的数为:</Label>
            <Label Name="lastLuckNumLabel" FontSize="18" HorizontalContentAlignment="Center"></Label>
        </DockPanel>

    </StackPanel>
</Window>

实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace 摇奖机
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool IsRoll = false;
        List<string> _randomNumList = new List<string>();
        string _currentLucknum;//存储当前奖号
        public MainWindow()
        {
            InitializeComponent();
            btnStart.Click += BtnStart_Click;//注册事件
        }
        /// <summary>
        /// 按钮事件
        /// </summary>
        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            Thread RollNumLableThread = new Thread(RollNumLableMethod);//创建线程
            if (btnStart.Content.Equals("开始"))
            {
                _currentLucknum = null;
                lastLuckNumLabel.Content = currentLuckNumLabel.Content;//赋值上次奖号
                currentLuckNumLabel.Content = null;//当前奖号置空


                IsRoll = true;
                btnStart.Content = "暂停";
                RollNumLableThread.IsBackground = true;//设置为线程
                RollNumLableThread.Start();
            }
            else if (btnStart.Content.Equals("暂停"))
            {
               
                IsRoll = false;
                RollNumLableThread.Abort();
                btnStart.Content = "开始";
                foreach (var item in _randomNumList)//将list元素连接成当前奖号成字符串
                {
                    _currentLucknum += item;//当前奖号
                }
                currentLuckNumLabel.Content = _currentLucknum;//赋值

            }
        }
        /// <summary>
        /// 线程执行方法
        /// </summary>
        private void RollNumLableMethod()
        {

            
            while (IsRoll)
            {
                this.Dispatcher.BeginInvoke((Action)delegate ()//由于线程无法直接操作另一个线程创建的控件,所以向UI线程中注册方法,
                {
                    int labelCount = VisualTreeHelper.GetChildrenCount(panel);//获取panel容器中的空间数量

                    List<string> randomNumList = RandomNum(labelCount);//根据数量生成labelCount 个0-9随机数
                    _randomNumList = randomNumList;

                    for (int i = 0; i < labelCount; i++)//遍历
                    {
                         DependencyObject child = VisualTreeHelper.GetChild(panel, i);//遍历控件
                         if (child != null && child is Label)//判断控件是否是label
                         {
                            Label numlable = child as Label;//里氏转换成label
                            numlable.Content = randomNumList[i];//赋值
                            //Console.WriteLine(randomNumList[i]);
                         }
                    }
                    
                });
                Thread.Sleep(100);//线程休眠100毫秒   /////线程休眠会导致一些异步的BUG,导致本次抽奖号与滚动抽奖号不一致///不晓得怎么解决了
            }
        }
       /// <summary>
       /// 生成随机数
       /// </summary>
       /// <param name="count">生成数量</param>
       /// <returns>返回随机数集合</returns>
        private List<string> RandomNum( int count)
        {
            List<string> randomList = new List<string>();
            Random randomNum = new Random();
            //如果将创建随机数对象放入循环中,造成生成的数是一样的。
            //一个随机函数,运行N次其实是不会生成同一个数的。只是被我们错误的在极短时间内初始化N次,生成了N个随机函数(时间很短所以几乎一样)。他们又被同时运行才生成同样的数字;
            for (int i = 0; i < count; i++)
            {
                int r = randomNum.Next(0, 10);
                randomList.Add(r.ToString());
            }
            return randomList;
            
        }
    }
}

效果

抽奖机效果.gif
上一篇下一篇

猜你喜欢

热点阅读