【WinForm】C#多线程Demo (线程池线程、异步任务、异步IO)

一、随机进度条状态-线程池线程

fad8649e92a3d92ae4e977e43dd56380.png

using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace Multithreading_Csharp_Winform
{
    //线程池线程演示
    public partial class Form1 : Form
    {
        List<ProgressBar> progressBars;
        bool started;
        public Form1()
        {
            InitializeComponent();
            progressBars = new List<ProgressBar>();
            started = false;
        }
        //开始 前先生成进度条
        private void button2_Click(object sender, EventArgs e)
        {
            Button button = (Button)sender;
            if (button.Text == "start")
            {
                buttonGenerateProgressBars.Enabled = false;
                button.Text = "stop";
                started = true;


                foreach (ProgressBar progressBar in progressBars)
                {
                    //将方法排队以供执行,并指定包含该方法要使用的数据的对象。该方法在线程池线程变为可用时执行。
                    ThreadPool.QueueUserWorkItem(StartBar, progressBar);//
                }
            }
            else
            {
                buttonGenerateProgressBars.Enabled = true;
                button.Text = "start";
                started = false;
            }
        }
        //线程池线程的方法:state为传入的 进度条对象
        private void StartBar(object state)
        {
            ProgressBar progressBar = (ProgressBar)state;//拆箱
            Random random = new Random();
            while (started)
            {
                this.Invoke(new Action(()=> {
                    progressBar.Value = random.Next(0, 100);//随机状态条值
                }));
                Thread.Sleep(600);
            }
        }
        //生成进度条
        private void buttonGenerateProgressBars_Click(object sender, EventArgs e)
        {
            //移除所有进度条
            if (progressBars.Count > 0)
            {
                foreach (ProgressBar progressBar in progressBars)
                {
                    this.Controls.Remove(progressBar);
                }
                progressBars.Clear();
            }
            int count = Convert.ToInt32(numericUpDown1.Value);//进度条数
            int num1;//可用的工作线程数。
            int available;//可用的异步I/O线程数
            //检索System.Threading.ThreadPool.GetMaxThreads(System.Int32@,System.Int32@)方法返回的最大线程池线程数与当前活动的线程数之间的差值
            ThreadPool.GetAvailableThreads(out num1, out available);
            //在切换到管理线程创建和销毁的算法之前,设置线程池在发出新请求时按需创建的最小线程数。
            ThreadPool.SetMinThreads(count, available);//线程池按需创建的最小工作线程数 count     线程池按需创建的最小异步I/O线程数available


            int yCoord = 50;
            int xCoord = 10;
            bool rightToLeft = false;
            Random random = new Random();
            //创建进度条
            for (int i = 0; i < count; i++)
            {
                ProgressBar progressBar = new ProgressBar();
                progressBar.Width = 700;
                progressBar.Height = 23;


                progressBar.Top = yCoord;
                progressBar.Left = xCoord;


                if (rightToLeft)
                {
                    progressBar.RightToLeft = RightToLeft.Yes;
                    //获取或设置一个值,该值指示是否从右向左显示System.Windows.Forms.ProgressBar及其包含的任何文本。
                    progressBar.RightToLeftLayout = rightToLeft;
                    rightToLeft = false;
                }
                else
                {
                    rightToLeft = true;
                }


                progressBar.SetState(random.Next(0, 4));//设置进度条随机位置


                this.Controls.Add(progressBar);//显示控件


                yCoord = progressBar.Top + 23;//更新进度条位置y


                progressBars.Add(progressBar);//添加到进度条列表
            }
        }
        //下一演示
        private void button1_Click(object sender, EventArgs e)
        {
            HorseRacing horseRacing = new HorseRacing();
            this.Visible = false;
            started = false;
            horseRacing.ShowDialog();
            this.Close();
        }
    }
}

二、进度条比赛-线程池线程

72ed4f7582c9a8eae8392d794a83ef9c.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;


namespace Multithreading_Csharp_Winform
{
    public partial class HorseRacing : Form
    {
        List<ProgressBar> progressBars;
        bool won;
        public HorseRacing()
        {
            InitializeComponent();
            won = true;
            progressBars = new List<ProgressBar>() { Horse1, Horse2, Horse3, Horse4, Horse5 };//进度条列表
            int i = 1;
            foreach (ProgressBar progressBar in progressBars)
            {
                progressBar.Name = $"Horse {i++}";//重命名进度条
            }
            int num1;
            int available;


            ThreadPool.GetAvailableThreads(out num1, out available);
            //在切换到管理线程创建和销毁的算法之前,设置线程池在发出新请求时按需创建的最小线程数。
            ThreadPool.SetMinThreads(5, available);
        }
        //开始/结束
        private void button2_Click(object sender, EventArgs e)
        {
            if (!won)
            {
                won = true;//赢了
                MessageBox.Show("Stopped");
            }
            else//
            {
                won = false;
                foreach (ProgressBar progressBar in progressBars)
                {
                    progressBar.Value = 0;//重置进度条的值
                }
                foreach (ProgressBar progressBar in progressBars)
                {
                    ThreadPool.QueueUserWorkItem(StartRace, progressBar);//进度条比赛线程
                }
            }
        }
        //开始比赛
        private void StartRace(object state)
        {
            ProgressBar progressBar = (ProgressBar)state;
            Random random = new Random();
            int speed;
            int num;
            while (!won)
            {
                speed = random.Next(20);
                num = progressBar.Value + random.Next(0, speed);
                this.Invoke(new Action(()=> {
                    progressBar.Value = (num > 100 ? 100 : num);
                }));
                Thread.Sleep(500);
                if (progressBar.Value == 100)//有进度条满了
                {
                    won = true;
                    MessageBox.Show($"{progressBar.Name} won!");
                }
            }
        }
        //下一演示
        private void button1_Click(object sender, EventArgs e)
        {
            Fiponachi fiponachi = new Fiponachi();
            this.Visible = false;
            won = true;
            fiponachi.ShowDialog();
            this.Close();
        }
    }
}

三、计算斐波那契数列满足指定条件时的个数--异步任务

d5039032936e95f4fa8308ab22672cc1.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace Multithreading_Csharp_Winform
{
    public partial class Fiponachi : Form
    {
        public Fiponachi()
        {
            InitializeComponent();
        }
        //斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...
        public Task<int> FibAsync(int stopNum)
        {
            int tmp;
            int numbers = 0;
            for (int firstNum = 0, secNum = 1; secNum + firstNum <= stopNum; numbers++)
            {
                tmp = secNum;
                secNum += firstNum;
                firstNum = tmp;
            }
            return Task.FromResult(numbers);//返回Task<TResult>  
        }
        //异步方法:
        private async void button2_Click(object sender, EventArgs e)
        {
            int res = await FibAsync(Convert.ToInt32(numericUpDown1.Value));//等待任务返回
            MessageBox.Show($"Result: {res}!");
        }
        //下一演示
        private void button1_Click(object sender, EventArgs e)
        {
            FindWordFile findWordFile = new FindWordFile();
            this.Visible = false;
            findWordFile.ShowDialog();
            this.Close();
        }
    }
}

四、在文件内容里查找word--异步读取文件

520566eb5017bca98449f230d0034f72.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace Multithreading_Csharp_Winform
{
    public partial class FindWordFile : Form
    {
        string path;
        public FindWordFile()
        {
            InitializeComponent();
            path = String.Empty;
        }
        //选择路径文件
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "All files(*.*)|*.*";
            if (ofd.ShowDialog() != DialogResult.Cancel)
            {
                label1.Text = $"path: {ofd.FileName}";
                path = ofd.FileName;
            }
        }
        //开始  异步读取文件内容
        private void button2_Click(object sender, EventArgs e)
        {
            if (path == String.Empty)
            {
                MessageBox.Show("Choose file");
                return;
            }
            string result;
            using (FileStream fs = new FileStream(path, FileMode.Open))//打开文件
            {
                byte[] arr = new byte[fs.Length];
                //开始异步读取操作。请考虑改用System.IO.FileStream.ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)。
                IAsyncResult asyncResult = fs.BeginRead(arr, 0, arr.Length, null, null);
                //等待挂起的异步读取操作完成。(请考虑改用System.IO.FileStream.ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)。)
                fs.EndRead(asyncResult);
                result = Encoding.UTF8.GetString(arr);
            }
            MessageBox.Show($"Find: {result.Split($"{textBox1.Text}").Length - 1}");//用要查找的word 来分割内容
        }
        //下一演示
        private void button3_Click(object sender, EventArgs e)
        {
            FindWordDir findWordDir = new FindWordDir();
            this.Visible = false;
            findWordDir.ShowDialog();
            this.Close();
        }
    }
}

五、在文件夹下查找包含word的文件--线程池线程、异步IO

f331f0dc70c98752ab63c2144e2a5b0d.png

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace Multithreading_Csharp_Winform
{
    public partial class FindWordDir : Form
    {
        string path;//文件夹
        bool stop;
        int filesInProcessing;


        public FindWordDir()
        {
            InitializeComponent();
            stop = true;
            filesInProcessing = 0;//正在处理的文件数
            label3.Text = String.Empty;
        }
        //选择文件夹
        private void button1_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            if (folderBrowserDialog.ShowDialog() != DialogResult.Cancel)
            {
                label1.Text = $"path: {folderBrowserDialog.SelectedPath}";
                path = folderBrowserDialog.SelectedPath;
            }
        }
        //开始
        private void button2_Click(object sender, EventArgs e)
        {
            if (path == String.Empty)
            {
                MessageBox.Show("Choose folder");
                return;
            }
            else if (stop == false && filesInProcessing != 0)
            {
                MessageBox.Show("Finding word");
            }
            stop = false;
            //在线程池上运行任务 
            Task.Run(() =>
            {
                FindWordInFolder(path);//在目录里查找
                label3.Text = "Search in progress..";
                while (true)
                {
                    if (stop)
                    {
                        while (filesInProcessing > 0)
                        {
                            //查找中
                        }
                        //所有文件都遍历完后
                        label3.Text = "Done";
                        break;
                    }
                }
            });
        }
        //在文件夹查找包含textBox1.Text的文件
        private void FindWordInFolder(object state)
        {
            string dirPath = (string)state;
            IEnumerable<string> directories = Directory.EnumerateDirectories(dirPath);//文件夹爱下的所有目录
            IEnumerable<string> files = Directory.EnumerateFiles(dirPath);//文件夹下所有文件路径


            foreach (string folderPath in directories)
            {
                ThreadPool.QueueUserWorkItem(FindWordInFolder, folderPath);//在文件夹里查找内容
            }


            foreach (string filePath in files)
            {
                ThreadPool.QueueUserWorkItem(FindWordInFile, filePath);//在文件里查找内容
                Interlocked.Increment(ref filesInProcessing);//递增指定的变量并将结果存储为原子操作。
            }
            stop = true;
        }
        //在文件里查找内容textBox1.Text
        private void FindWordInFile(object state)
        {
            string filePath = (string)state;
            try
            {
                //读取文件内容
                string result;
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    byte[] arr = new byte[fs.Length];
                    IAsyncResult asyncResult = fs.BeginRead(arr, 0, arr.Length, null, null);
                    fs.EndRead(asyncResult);
                    result = Encoding.UTF8.GetString(arr);
                }
                //查找word
                int count = result.Split($"{textBox1.Text}").Length - 1;
                string[] str = result.Split($"{textBox1.Text}");
                if (count > 0)
                {
                    lock (textBox2)
                    {
                        textBox2.Text += $"Found: {count} \"{textBox1.Text}\" in {filePath}\r\n";//在某个文件中找到该内容多少次
                    }
                }
            }
            catch (Exception)
            {
                MessageBox.Show($"Error while reading file: {filePath}");
            }
            finally
            {
                Interlocked.Decrement(ref filesInProcessing);
            }
        }
    }
}

进度条状态设置方法:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;


namespace Multithreading_Csharp_Winform
{
    public static class ModifyProgressBarColor
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
        public static void SetState(this ProgressBar pBar, int state)//设置 进度条状态
        {
            SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
        }
    }
}

The End

猜你喜欢

转载自blog.csdn.net/cxyhjl/article/details/129631261