美文网首页
WPF 实现抽奖机

WPF 实现抽奖机

作者: Memoyu | 来源:发表于2019-04-23 17:04 被阅读0次

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

    概述

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


    踩的坑

    • 最大的坑在于随机数的产生方法。方法根据奖号label的个数产生相应个数随机数字,我将创建随机数对象放入循环中,导致生成的随机数完全一致。移除循环后才恢复正常。具体原因查看注释或请移步:https://blog.csdn.net/w790634493/article/details/39122745


    • 最后就是对线程不太熟悉,未能解决开篇的问题。

    代码

    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

    相关文章

      网友评论

          本文标题:WPF 实现抽奖机

          本文链接:https://www.haomeiwen.com/subject/paxbgqtx.html