新建WinFrom项目,在界面上添加两个按钮
分别用Thread和Task实现进度条效果
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//普通Thread实现进度条
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("主线程开始");
new Thread(DoProcessing).Start(); //没有使用线程池,每次调用都开启新线程
//ThreadPool.QueueUserWorkItem(DoProcessing);//使用线程池,重复开启的时候回去线程池拿空闲的线程
Console.WriteLine("主线程结束");
}
//在方法上加上 async
private async void button2_Click(object sender, EventArgs e)
{
await UpdateUi2();
//async.await的语法糖为我们带来了更好的异步编程体验
}
#region Thread
void UpdateUi(int percent)
{
//UI操作
button1.Text = string.Format("{0}%", percent);
}
void DoProcessing(object obj)
{
for (int i = 0; i <= 5; ++i)
{
Thread.Sleep(500);
Console.WriteLine("---------- " + i);
Action<int> updateUi = new Action<int>(UpdateUi);
this.Invoke(updateUi, i);
}
}
#endregion
#region task,async,await
private static int _percent = 0;
int DoProcessing2()
{
Console.WriteLine("Thread id in DoProcessing: {0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(500);
return ++_percent;
}
async Task UpdateUi2()
{
_percent = 0;
button1.Text = string.Format("{0}%", 0);
while (_percent < 5)
{
//await起到释放主线程的作用
int percent = await Task.Run(() => DoProcessing2());
//在子线程处理完成后,又请求主线程继续下面的代码,下面的代码相当于Thread的回调
button2.Text = string.Format("{0}%", percent);
}
}
#endregion
#region 参考
private void button3_Click(object sender, EventArgs e)
{
Thread.Sleep(3000); //堵塞主线程
button1.Text = string.Format("99%");
}
#endregion
}
}
C# 同步方法改异步方法
先举例一个同步方法 Greeting 开始,该方法等待一段时间后,返回一个字符串:
static string Greeting(string name)
{
TraceThreadAndTask($"running {nameof(Greeting)}");
Task.Delay(3000).Wait();
return $"Hello, {name}";
}
同步改异步
定义方法 GreetingAsync,可以使方法异步化。基于任务的异步模式指定,在异步方法名后加上 Async 后缀,并返回一个任务。异步方法 GreetingAsync 和同步方法 Greeting 具有相同的输入参数,但是它返回的是 Task。Task 定义了一个返回字符串的任务。一个比较简单的做法是用 Task.Run 方法返回一个任务。泛型版本的 Task.Run() 创建一个返回字符串的任务。由于编译器已经知道实现的返回类型(Greeting返回字符串),因此还可以使用 Task.Run() 来简化实现代码:
static Task<string> GreetingAsync(string name) =>
Task.Run<string> (() =>
{
TraceThreadAndTask($"running {nameof(GreetingAsync)}");
return Greeting(name);
});