同步、异步、并发、异步回调的使用。
通过查询书籍名称,并打印出来为例子讲解, 使用winform,设计“同步执行”、“”异步执行“、“并发执行””、“异步回调”按钮,和一个textbox显示框
/// <summary>
/// 同步
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_sync_Click(object sender, EventArgs e)
{
Stopwatch sw =Stopwatch.StartNew();
resultTextBox.Clear();
AppendLine("同步检索开始……");
int idx = 0;
Data.Books.ForEach(x => AppendLine($"{++idx}.{x.Search()}"));
sw.Stop();
AppendLine($"同步检索完成:{Convert.ToSingle(sw.ElapsedMilliseconds)/1000}秒");
}
/// <summary>
/// 异步
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void btn_asyn_Click(object sender, EventArgs e)
{
Stopwatch sw =Stopwatch.StartNew();
resultTextBox.Clear();
AppendLine("异步检索开始……");
int idx = 0;
foreach (var book in Data.Books)
{
var task = await Task.Run(book.Search).ConfigureAwait(false); //为了使返回时进入线程池来执行后续方法 提高效率
AppendLineThread($"{++idx}.{task}");
}
sw.Stop();
AppendLineThread($"异步检索完成:{Convert.ToSingle((sw.ElapsedMilliseconds) / 1000)}秒");
}
/// <summary>
/// 并发 异步解决了卡UI线程问题 但不能提高效率
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void byn_concu_Click(object sender, EventArgs e)
{
Stopwatch sw = Stopwatch.StartNew();
resultTextBox.Clear();
AppendLine("并行检索开始……");
int idx = 0;
List<Task<string>> Tasks = new(); //线程集合,
Data.Books.ForEach(x=>Tasks.Add(Task.Run(x.Search))); // 线程返回值string
var tasks=await Task.WhenAll(Tasks); //当所有的线程都运行完之后
foreach (var result in tasks)
{
AppendLine($"{++idx}.{result}");
}
sw.Stop();
AppendLine($"并行检索完成:{Convert.ToSingle((sw.ElapsedMilliseconds) / 1000)}秒");
}
private void AppendLine(string text)
{
resultTextBox.AppendText(string.IsNullOrEmpty(resultTextBox.Text)?text:$"{Environment.NewLine}{text}");
resultTextBox.ScrollToCaret();
resultTextBox.Refresh();
}
/// <summary>
/// 异步回调 线程哪一个先结束,继续往下执行
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_AsyncCallback_Click(object sender, EventArgs e)
{
Stopwatch sw = Stopwatch.StartNew();
resultTextBox.Clear();
AppendLine("异步回调检索开始……");
int idx = 0;
foreach (var book in Data.Books)
{
Task.Run(book.Search).ContinueWith(t => AppendLineThread($"{++idx}.{t.Result}")); //Ui线程在此处没有等待,所以没有办法等到所有线程都执行完
}
sw.Stop();
AppendLine($"异步回调检索完成:{Convert.ToSingle(sw.ElapsedMilliseconds) / 1000}秒"); //主线程在此处没有进行等待
}
/// <summary>
/// 将打印线程委托给UI线程来执行
/// </summary>
/// <param name="text"></param>
private void AppendLineThread(string text)
{
this.Invoke((() => AppendLine(text)));
}
public class Data
{
/// <summary>
/// 书目集合
/// </summary>
public readonly static List<Book> Books = new()
{
new Book("封神演义", 1), //时长
new Book("三国演义", 2),
new Book("西游记", 1),
new Book("红楼梦", 1),
new Book("聊斋志异", 2),
new Book("玉林外史", 1),
new Book("朝花夕拾", 1),
new Book("水浒传", 1),
};
}
public class Book
{
public string? Name { get; }
public int Duration { get; } //查询测试延时时间
public Book(string name,int second)
{
Name = name;
Duration= second;
}
private string Result(long milliseconds)
{
return $"{Name.PadRight(12,'-')} 用时: {Convert.ToSingle(milliseconds)/1000}秒";
}
//检索
public string Search()
{
Stopwatch sw = Stopwatch.StartNew();
//检索逻辑
Thread.Sleep(Duration * 1000);
//……
sw.Stop();
//制作完成,返回消息
return Result(sw.ElapsedMilliseconds);
}
}