本帖最后由 Cool_Breeze 于 2021-5-24 11:30 编辑
请务必将任务理解为工作的异步抽象,而非 在线程之上的抽象。 默认情况下,任务在当前线程上执行,且在适当时会将工作委托给操作系统。
解决了。异步执行时,主线程会收到终止异常。所以需要在主线程中终止任务后,在开始新的任务![C#] 纯文本查看 复制代码 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;
}} |