Wpf使用radiobutton实现线程同步异步的练习

Wpf使用radiobutton实现线程同步异步的练习

背景

日常练习,使用thread、threadpool、task实现同步异步页面更新。

代码

View

<Window x:Class="WPFToDoList.View.RandomGameView"
        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:WPFToDoList.View"
        xmlns:vm="clr-namespace:WPFToDoList.ViewModel"
        DataContext=""
        mc:Ignorable="d"
        Title="RandomGame" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
        </Grid.RowDefinitions>
        <WrapPanel Orientation="Horizontal" Grid.Row="0">
            <StackPanel Orientation="Horizontal">
                <RadioButton GroupName="gp1" Content="使用Thead" Margin="0,0,5,0" Tag="1" Command="{Binding RadioBtnGameCommand}"
                             CommandParameter="{Binding Tag,RelativeSource={RelativeSource Self}}"/>
                <RadioButton GroupName="gp1" Content="使用Task"  Margin="0,0,5,0"  Tag="2" Command="{Binding RadioBtnGameCommand}"
                             CommandParameter="{Binding Tag,RelativeSource={RelativeSource Self}}" />
                <RadioButton GroupName="gp1" Content="使用TheadPool"  Margin="0,0,5,0" Tag="3" Command="{Binding RadioBtnGameCommand}"
                             CommandParameter="{Binding Tag,RelativeSource={RelativeSource Self}}" />
                <RadioButton GroupName="gp1" Content="使用TPL"  Margin="0,0,5,0" Tag="4" Command="{Binding RadioBtnGameCommand}"
                             CommandParameter="{Binding Tag,RelativeSource={RelativeSource Self}}" />
            </StackPanel>
            <StackPanel >
                <Button x:Name="btnStart" Command="{Binding StartGameCommand}" Content="开始游戏" Width="100"></Button>
            </StackPanel>
        </WrapPanel>
        <WrapPanel Orientation="Vertical" Grid.Row="1">
            <StackPanel Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算式1"  Margin="10"/>
                <TextBlock Text="参数1" Margin="10"/>
                <TextBox Text="{Binding Param11}" Margin="10" Width="100"/>
                <TextBlock Text="参数2" Margin="10"/>
                <TextBox Text="{Binding Param12}" Margin="10" Width="100"/>
                <TextBlock Text="结果" Margin="10"/>
                <TextBox Text="{Binding Answer1}" Margin="10" Width="100"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算式2"  Margin="10"/>
                <TextBlock Text="参数1" Margin="10"/>
                <TextBox Text="{Binding Param21}" Margin="10" Width="100"/>
                <TextBlock Text="参数2" Margin="10"/>
                <TextBox Text="{Binding Param22}" Margin="10" Width="100"/>
                <TextBlock Text="结果" Margin="10"/>
                <TextBox Text="{Binding Answer2}" Margin="10" Width="100"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算式3"  Margin="10"/>
                <TextBlock Text="参数1" Margin="10"/>
                <TextBox Text="{Binding Param31}" Margin="10" Width="100"/>
                <TextBlock Text="参数2" Margin="10"/>
                <TextBox Text="{Binding Param32}" Margin="10" Width="100"/>
                <TextBlock Text="结果" Margin="10"/>
                <TextBox Text="{Binding Answer3}" Margin="10" Width="100"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算式4"  Margin="10"/>
                <TextBlock Text="参数1" Margin="10"/>
                <TextBox Text="{Binding Param41}" Margin="10" Width="100"/>
                <TextBlock Text="参数2" Margin="10"/>
                <TextBox Text="{Binding Param42}" Margin="10" Width="100"/>
                <TextBlock Text="结果" Margin="10"/>
                <TextBox Text="{Binding Answer4}" Margin="10" Width="100"/>
            </StackPanel>
            <StackPanel  Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算完成数量" Margin="10"></TextBlock>
                <TextBox Text="{Binding DoneCount}" Margin="10" Width="100"></TextBox>
                <TextBlock Text="个" Margin="10"></TextBlock>
            </StackPanel>
            <StackPanel  Orientation="Horizontal" Margin="5">
                <TextBlock Text="计算完成顺序" Margin="10"></TextBlock>
                <TextBox Text="{Binding DoneSort}" Margin="10" Width="100"></TextBox>
            </StackPanel>
        </WrapPanel>

    </Grid>
</Window>

ViewModel

using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using WPFDevelopers.Controls;
using WPFToDoList.View;

namespace WPFToDoList.ViewModel
{
    /// <summary>
    /// 练习多线程的小游戏
    /// </summary>
    class RandomGameViewModel : BindableBase, INavigationAware
    {
        TaskViewModel viewModel;

        public RandomGameViewModel(TaskViewModel viewModel)
        {
            this.viewModel = viewModel;
            Param11 = 1;
            Param12 = 1;
            Param21 = 1;
            Param22 = 1;
            Param31 = 1;
            Param32 = 1;
            Param41 = 1;
            Param42 = 1;
            Answer1 = 0;
            Answer2 = 0;
            Answer3 = 0;
            Answer4 = 0;
            DoneCount = 0;
            DoneSort = "";
        }

        private RelayCommand radioBtnGameCommand;
        /// <summary>
        /// Check
        /// </summary>
        public RelayCommand RadioBtnGameCommand
        {
            get
            {
                if (radioBtnGameCommand == null)
                    radioBtnGameCommand = new RelayCommand(RadioBtnGameCommand_Execute);
                return radioBtnGameCommand;
            }
            set { radioBtnGameCommand = value; }
        }

        private void RadioBtnGameCommand_Execute(object obj)
        {
            SelectedValue = Convert.ToInt32(obj);
        }

        private RelayCommand startGameCommand;
        /// <summary>
        /// 多线程游戏
        /// </summary>
        public RelayCommand StartGameCommand
        {
            get
            {
                if (startGameCommand == null)
                    startGameCommand = new RelayCommand(StartGameCommand_Execute);
                return startGameCommand;
            }
            set { startGameCommand = value; }
        }

        private void StartGameCommand_Execute(object obj)
        {
            GameStart();
        }

        private async void GameStart()
        {
            UpdateDoneCount("resume");
            switch (SelectedValue)
            {
                case 1:
                    Thread thread1 = new Thread(new ThreadStart(() => Add(param11, param12, "1")));
                    Thread thread2 = new Thread(new ThreadStart(() => Add(param21, param22, "2")));
                    Thread thread3 = new Thread(new ThreadStart(() => Add(param31, param32, "3")));
                    Thread thread4 = new Thread(new ThreadStart(() => Add(param41, param42, "4")));

                    // 启动线程
                    thread1.Start();
                    thread2.Start();
                    thread3.Start();
                    thread4.Start();
                    // 等待所有线程完成
                    thread1.Join();
                    thread2.Join();
                    thread3.Join();
                    thread4.Join();
                    break;
                case 3:
                    ThreadPool.QueueUserWorkItem(new WaitCallback(Add2), new object[] { param11, param12, "1" });
                    ThreadPool.QueueUserWorkItem(new WaitCallback(Add2), new object[] { param21, param22, "2" });
                    ThreadPool.QueueUserWorkItem(new WaitCallback(Add2), new object[] { param31, param32, "3" });
                    ThreadPool.QueueUserWorkItem(new WaitCallback(Add2), new object[] { param41, param42, "4" });
                    break;
                case 2:
                    Task task31 = Task.Run(new Action(() => Add(param11, param12, "1")));
                    Task task32 = Task.Run(new Action(() => Add(param21, param22, "2")));
                    Task task33 = Task.Run(new Action(() => Add(param31, param32, "3")));
                    Task task34 = Task.Run(new Action(() => Add(param41, param42, "4")));
                    Task.WaitAll(task31, task32, task33, task34);
                    break;
                case 4:
                    Task task41 = Task.Run(new Action(() => Add(param11, param12, "1")));
                    Task task42 = Task.Run(new Action(() => Add(param21, param22, "2")));
                    Task task43 = Task.Run(new Action(() => Add(param31, param32, "3")));
                    Task task44 = Task.Run(new Action(() => Add(param41, param42, "4")));
                    await Task.WhenAll(task41, task42, task43, task44);
                    break;
                default:
                    break;
            }
        }

        private void Add(double param1, double param2, string tag)
        {
            double ans = 0;
            for (int i = 0; i < 10; i++)
            {
                ans += (param1 + param2);
            }
            switch (tag)
            {
                case "1":
                    Answer1 = ans;
                    break;
                case "2":
                    Answer2 = ans;
                    break;
                case "3":
                    Answer3 = ans;
                    break;
                case "4":
                    Answer4 = ans;
                    break;
                default:
                    break;
            }
            UpdateDoneCount(tag);
        }

        private void Add2(object arr)
        {
            object[] parameters = arr as object[];
            double ans = 0;
            for (int i = 0; i < 10; i++)
            {
                ans += (Convert.ToDouble(parameters[0]) + Convert.ToDouble(parameters[1]));
            }
            switch (parameters[2].ToString())
            {
                case "1":
                    Answer1 = ans;
                    break;
                case "2":
                    Answer2 = ans;
                    break;
                case "3":
                    Answer3 = ans;
                    break;
                case "4":
                    Answer4 = ans;
                    break;
                default:
                    break;
            }
            UpdateDoneCount(parameters[2].ToString());
        }
        public static readonly object locker = new object();

        private void UpdateDoneCount(string num)
        {
            lock (locker)
            {
                if (num.Equals("resume"))
                {
                    DoneCount = 0;
                    DoneSort = "";
                }
                else
                {
                    DoneCount += 1;
                    DoneSort += num;
                }
            }
        }

        private int _selectedValue;
        public int SelectedValue
        {
            get { return _selectedValue; }
            set
            {
                SetProperty(ref _selectedValue, value);
            }
        }

        private double param11;
        public double Param11
        {
            get { return param11; }
            set { SetProperty(ref param11, value); }
        }

        private double param12;
        public double Param12
        {
            get { return param12; }
            set { SetProperty(ref param12, value); }
        }


        private double answer1;
        public double Answer1
        {
            get { return answer1; }
            set { SetProperty(ref answer1, value); }
        }

        private double param21;
        public double Param21
        {
            get { return param21; }
            set { SetProperty(ref param21, value); }
        }

        private double param22;
        public double Param22
        {
            get { return param22; }
            set { SetProperty(ref param22, value); }
        }


        private double answer2;
        public double Answer2
        {
            get { return answer2; }
            set { SetProperty(ref answer2, value); }
        }

        private double param31;
        public double Param31
        {
            get { return param31; }
            set { SetProperty(ref param31, value); }
        }

        private double param32;
        public double Param32
        {
            get { return param32; }
            set { SetProperty(ref param32, value); }
        }


        private double answer3;
        public double Answer3
        {
            get { return answer3; }
            set { SetProperty(ref answer3, value); }
        }

        private double param41;
        public double Param41
        {
            get { return param41; }
            set { SetProperty(ref param41, value); }
        }

        private double param42;
        public double Param42
        {
            get { return param42; }
            set { SetProperty(ref param42, value); }
        }


        private double answer4;
        public double Answer4
        {
            get { return answer4; }
            set { SetProperty(ref answer4, value); }
        }

        private double doneCount;
        public double DoneCount
        {
            get { return doneCount; }
            set { SetProperty(ref doneCount, value); }
        }

        private string doneSort;
        public string DoneSort
        {
            get { return doneSort; }
            set { SetProperty(ref doneSort, value); }
        }


        #region 页面导航
        //需要继承INavigationAware接口,实现接口中三个方法
        //三个方法的执行顺序:
        //1.Main====>PageA
        //先执行Main页面的OnNavigatedFrom,再执行PageA页面的OnNavigatedTo
        //2.PageA====>PageA
        //OnNavigatedFrom()----->IsNavigationTarget()----->OnNavigatedTo()
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            //每次重新导航时,是否重新创建当前PageBViewModel实例,
            //return true;时就不会再创建新的实例(不会再次运行当前PageBViewModel构造函数)
            return true;
        }

        /// <summary>
        /// // 从这个ViewModel导航离开时的逻辑
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// // 导航到此ViewModel时的逻辑
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}

练习一下基本功,接下来回去做一个上位机的demo,了解一下串口通信。

现在基本掌握了wpf常用控件、页面绘制、依赖属性、数据绑定、命令、事件、导航等等基础能力。

更深入的部分后续会跟着视频博主细致学习。

再去背一背面试常问到的题,八月初准备去第二轮投递简历了。

anyway,aim to find a ideal job~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值