可以先看前面的backgroudwork文章,再看Thread文章,本demo接着Thread的环境继续。
本demo演示的是:
Task有三种写法,喜欢那种就选择那种。
并且在Task中进行停止,暂停,继续的功能。
开始。
1.界面业务说明,label1是加法计算,分别有3个功能,对label1停止加法,暂停加法,继续加法。100 是减法计算。
2.load中加载Task
第一种写法用new
var task1 = new Task(() =>
{
A();
});
task1.Start();
var task2 = new Task(() =>
{
B();
});
task2.Start();
第二种写法用StartNew
Task t1 = Task.Factory.StartNew(() => {
A();
});
Task t2 = Task.Factory.StartNew(() => {
B();
});
第三种写法用Run
Task t1 = Task.Run(() =>
{
A();
});
Task t2 = Task.Run(() =>
{
B();
});
也可以不写赋值变量,直接运行
Task.Run(() =>
{
A();
});
Task.Run(() =>
{
B();
});
3.下面是 A B方法
public void A()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
Invoke(new Action(() => label1.Text = i.ToString()));
}
}
public void B()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
Invoke(new Action(() => label2.Text = (Convert.ToInt16(label2.Text) - 1).ToString()));
}
}
以上代码复制进去,可以进行独立的运行。
在Task中进行停止,暂停,继续的功能。停止后是不能继续的。
停止按钮的代码
先声明变量token和resetEvent
CancellationToken token;
ManualResetEvent resetEvent = new ManualResetEvent(true);
停止按钮的代码
var tokenSource = new CancellationTokenSource();
token = tokenSource.Token;
tokenSource.Cancel();
暂停按钮的代码
resetEvent.Reset();
继续按钮的代码
resetEvent.Set();
A方法
public void A()
{
for (int i = 0; i < 100; i++)
{
if (token.IsCancellationRequested)//这个是加法停止的判断
{
return;
}
resetEvent.WaitOne();//相当于把resetEvent和线程task1进行绑定
Thread.Sleep(1000);
Invoke(new Action(() => label1.Text = i.ToString()));
}
}
token.IsCancellationRequested是加法停止的判断
resetEvent.WaitOne();//相当于把resetEvent和线程task1进行“绑定”,从而可以控制线程task1
方法B不变
public void B()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
Invoke(new Action(() => label2.Text = (Convert.ToInt16(label2.Text) - 1).ToString()));
}
}
load进行调用:
var task1 = new Task(() =>
{
A();
}, token);//这里不写token,好像也可以
task1.Start();
var task2 = new Task(() =>
{
B();
});
task2.Start();
token这里可以不写,也可以写,不清楚是不是因为 resetEvent.WaitOne();进行“绑定”过了,知道的人可以说一下哦。
效果:
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
CancellationToken token;
ManualResetEvent resetEvent = new ManualResetEvent(true);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var task1 = new Task(() =>
{
A();
}, token);//这里不写token,好像也可以
task1.Start();
var task2 = new Task(() =>
{
B();
});
task2.Start();
}
public void A()
{
for (int i = 0; i < 100; i++)
{
if (token.IsCancellationRequested)//这个是加法停止的判断
{
return;
}
resetEvent.WaitOne();//相当于把resetEvent和线程task1进行绑定
Thread.Sleep(1000);
Invoke(new Action(() => label1.Text = i.ToString()));
}
}
public void B()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(1000);
Invoke(new Action(() => label2.Text = (Convert.ToInt16(label2.Text) - 1).ToString()));
}
}
/// <summary>
/// 停止线程
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
var tokenSource = new CancellationTokenSource();
token = tokenSource.Token;
tokenSource.Cancel();
}
/// <summary>
/// 继续
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
resetEvent.Set();
}
/// <summary>
/// 暂停
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
resetEvent.Reset();
}
}
}
拓展
//多个task
Task<string> t1 = File.ReadAllTextAsync("1.txt");
Task<string> t2= File.ReadAllTextAsync("1.txt");
Task<string> t3 = File.ReadAllTextAsync("1.txt");
string[] t = await Task.WhenAll(t1, t2, t3);
Task.Factory.StartNew比Task.Run有更多的参数选择项,偶尔也需要根据实际场景选择Task.Factory.StartNew,但是Task.Run的用法比较简介,已经可以满足大多数的场景
await Task.Run(A);
await Task.Factory.StartNew(A, TaskCreationOptions.LongRunning);
private void A()
{
}