WPF 实现抽奖机
2019-04-23 本文已影响0人
Memoyu
认知尚浅,如有错误,愿闻其详!
概述
近期学习到了线程,有个作业就是做一个滚动抽奖机,实现的过程中也遇到了一些问题,总结一下。
而且仍然存在着一个问题,就是问题出在线程休眠,导致获取到的随机奖号List集合与label上显示的可能不一致。有点愚钝,没找到解决方法。
踩的坑
- 最大的坑在于随机数的产生方法。方法根据奖号label的个数产生相应个数随机数字,我将创建随机数对象放入循环中,导致生成的随机数完全一致。移除循环后才恢复正常。具体原因查看注释或请移步:https://blog.csdn.net/w790634493/article/details/39122745
- 其次是子线程修改UI控件(Label)的问题,不懂的可以移步这里:https://www.jianshu.com/p/58eca851dfba
- 最后就是对线程不太熟悉,未能解决开篇的问题。
代码
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;
}
}
}