本帖最后由 Gin_Q 于 2021-5-24 11:31 编辑
认真阅读这句话:请务必 将任务理解为工作的异步抽象,而非 在线程之上的抽象。 默认情况下,任务在当前线程上执行,且在适当时会将工作委托给操作系统。 可选择性地通过 Task.Run API 显式请求任务在独立线程上运行。
解决了。异步执行时,当前线程会收到终止异常。所以需要在当前线程中终止任务后,随后捕获异常(为新任务开始做好准备)。再开始新的任务!- using System;
- using System.Drawing;
- using System.Threading;
- using System.IO;
- using System.Threading.Tasks;
- using System.Windows.Forms;
-
- public class Form1 : Form
- {
- [STAThread]
- public static void Main()
- {
- Application.EnableVisualStyles();
- Application.Run(new Form1());
- }
-
- private readonly ProgressBar pbar;
- private readonly Label label;
- private readonly Button StartPausebut;
- private readonly Button openFileBut;
- private readonly Button Stopbut;
- private readonly Button ShowHandle;
- private readonly ListBox fileList;
- private static CancellationTokenSource source = new CancellationTokenSource();
- private readonly EventWaitHandle StartPausebutEventsynchro = new EventWaitHandle(false, EventResetMode.ManualReset);
- private string selectFileName;
- private string oldSelectFileName;
- private Task task;
-
- // 窗体
- public Form1()
- {
- // 进度条
- pbar = new ProgressBar();
- pbar.Width = 500;
- pbar.Location = new Point(10, 20);
- pbar.Visible = true;
-
- // 开始,暂停按键
- StartPausebut = new Button();
- StartPausebut.Text = "开始";
- StartPausebut.Location = new Point(100, 60);
- StartPausebut.Click += new EventHandler(StartPausebut_Click);
-
- // 上一个
- Button selectUP = new Button();
- selectUP.Text = "上一个";
- selectUP.Location = new Point(10, 90);
- selectUP.Click += new EventHandler(selectUP_Click);
-
- // 下一个
- Button selectDown = new Button();
- selectDown.Text = "下一个";
- selectDown.Location = new Point(100, 90);
- selectDown.Click += new EventHandler(selectDown_Click);
-
- // 取消按键
- Stopbut = new Button();
- Stopbut.Text = "终止读取";
- Stopbut.Location = new Point(190, 60);
- Stopbut.Click += new EventHandler(Stopbut_Click);
-
- // 显示窗口句柄
- ShowHandle = new Button();
- ShowHandle.Text = "显示窗口句柄";
- ShowHandle.Location = new Point(280, 60);
- ShowHandle.Click += ShowHandle_Click;
-
- // 选择文件状态
- openFileBut = new Button();
- openFileBut.Text = "选择文件";
- openFileBut.Location = new Point(10, 60);
- openFileBut.Click += new EventHandler(openFileBut_Click);
-
- // 加载文件列表
- Button loadBut = new Button();
- loadBut.Text = "加载文件列表";
- loadBut.Width = 100;
- loadBut.Location = new Point(370, 60);
- loadBut.Click += new EventHandler(loadBut_Click);
-
- // 提示信息标签
- label = new Label();
- label.Location = new Point(10, 120);
- label.AutoSize = true;
-
- //文件列表内容
- fileList = new ListBox();
- fileList.Size = new System.Drawing.Size(500,400);
- fileList.Location = new Point(10, 140);
- fileList.MultiColumn = true;
-
- this.Controls.Add(StartPausebut);
- this.Controls.Add(pbar);
- this.Controls.Add(label);
- this.Controls.Add(Stopbut);
- this.Controls.Add(openFileBut);
- this.Controls.Add(ShowHandle);
- this.Controls.Add(fileList);
- this.Controls.Add(loadBut);
- this.Controls.Add(selectUP);
- this.Controls.Add(selectDown);
- this.Width = 600;
- this.Height = 600;
- }
-
- // 开始,暂停 按键事件
- private void StartPausebut_Click(object sender, EventArgs e)
- {
- Application.DoEvents();
-
- if (StartPausebut.Text == "开始")
- {
- StartPausebut.Text = "暂停";
- StartPausebutEventsynchro.Set(); // 任务非阻塞状态
- if (task == null || task.IsCompleted)
- {
- oldSelectFileName = selectFileName;
- task = Task.Run(() => openFileStream());
- }
- else if (selectFileName != oldSelectFileName)
- {
- Stopbut_Click(this, new EventArgs());
- task = Task.Run(() => openFileStream());
- StartPausebut.Text = "暂停";
- }
- return ;
- }
- else if (StartPausebut.Text == "暂停")
- {
- StartPausebut.Text = "开始";
- StartPausebutEventsynchro.Reset(); // 任务阻塞状态
- return ;
- }
- }
-
- // 选择文件
- private void openFileBut_Click(object sender, EventArgs e)
- {
- // 选择文件对话框
- OpenFileDialog dlg = new OpenFileDialog();
- dlg.Filter = "Text documents (*.*)|*.*";
- dlg.ShowDialog();
- selectFileName = dlg.FileName;
- label.Text = selectFileName;
- if (selectFileName == "")
- {
- return;
- }
-
- }
-
- // 取消任务
- private void Stopbut_Click(object sender, EventArgs e)
- {
- // if (!source.Token.IsCancellationRequested)
- try
- {
- if (task.Status != TaskStatus.RanToCompletion)
- {
- source.Cancel(); // 取消任务
- StartPausebutEventsynchro.Reset();
- Application.DoEvents();
- StartPausebutEventsynchro.Set();
- }
- else
- {
- return;
- }
- }
- catch {return;}
- try
- {
- task.Wait();
- }
- catch
- {
- StartPausebut.Text = "开始";
- source.Dispose();
- source = new CancellationTokenSource(); //重新获取取消任务对象
- }
- }
-
- // 显示窗口句柄
- private void ShowHandle_Click(object sender, EventArgs e)
- {
- label.Text = Handle.ToString("X");
- }
-
- // 文件内容读取(每次读取 4MB 内容)
- private async Task openFileStream()
- {
- pbar.Value = 0;
- // byte[] content = new byte[4194304];
- byte[] content = new byte[1024];
- int Count = 0;
- using (FileStream fr = new FileStream(selectFileName, FileMode.Open))
- {
- pbar.Maximum = (int)fr.Length; // 文件过大这里会内存溢出
- int total = 0;
- while (true)
- {
- // 阻塞线程事件
- // await Task.Run(() => StartPausebutEventsynchro.WaitOne());
- StartPausebutEventsynchro.WaitOne();
-
- source.Token.ThrowIfCancellationRequested();
- // 异步读取 100 字节 文件内容
- total = await fr.ReadAsync(content, 0, content.Length, source.Token);
-
- if (total == 0)
- {
- break;
- }
-
- // 进度条
- Count += total;
- label.Text = Count.ToString() + " 字节";
- pbar.Step = total;
- pbar.PerformStep();
- Application.DoEvents();
- }
- }
- StartPausebut.Text = "开始";
- }
-
- // 加载文件事件
- private void loadBut_Click(object sender, EventArgs e)
- {
- if (selectFileName == "" || selectFileName == null) return;
- fileList.BeginUpdate();
- fileList.Items.Clear();
- string filePath = Path.GetDirectoryName(selectFileName);
- foreach (var n in Directory.GetFiles(filePath))
- {
- fileList.Items.Add(n);
- }
- fileList.EndUpdate();
- }
-
- // 文件列表选中条上移
- private void selectUP_Click(object sender, EventArgs e)
- {
- if (fileList.Items.Count == 0) return;
- int count = fileList.Items.Count;
- int current = fileList.SelectedIndex;
- current--;
- if (current < 0)
- {
- current = count - 1;
- }
- fileList.SelectedIndex = current;
- label.Text = fileList.SelectedItem.ToString();
- selectFileName = label.Text;
- }
-
- // 文件列表选中条下移
- private void selectDown_Click(object sender, EventArgs e)
- {
- if (fileList.Items.Count == 0) return;
- int count = fileList.Items.Count;
- int current = fileList.SelectedIndex;
- current++;
- if (current >= count)
- {
- current = 0;
- }
- fileList.SelectedIndex = current;
- label.Text = fileList.SelectedItem.ToString();
- selectFileName = label.Text;
- }
- }
复制代码
|