C# 异步汇报任务
1.通过Task实现:
1 private async void button4_Click(object sender, EventArgs e) 2 { 3 button4.Enabled = false; 4 //此处不能用 5 //Dojob().Wait(); 6 7 await Dojob(); 8 button4.Enabled = true; 9 10 } 11 12 private async Task Dojob() 13 { 14 for (int i = 0; i <= 100; i++) 15 { 16 //ConfigureAwait(true)的作用是执行完await的任务后线程需要回到主线程,上面的wait会阻塞主线程,所以会产生死锁的现像, 17 //如果改为false ,是不会产生死锁,但下面的UI的操作会不在主线程,变成要用Invoke的写法,不是我想要的 18 await Task.Delay(10).ConfigureAwait(true); 19 progressBar1.Value = i; 20 21 } 22 }
2.使用Progress
1 private async void button4_Click3(object sender, EventArgs e) 2 { 3 button4.Enabled = false; 4 var progress = new Progress<double>(value=> progressBar1.Value = (int)value); 5 6 await Dojob(progress); 7 button4.Enabled = true; 8 9 } 10 11 private async Task Dojob3(IProgress<double> progress) 12 { 13 for (int i = 0; i <= 100; i++) 14 { 15 //此处不将线程交给UI线程,仍然能实现更新UI 16 await Task.Delay(10).ConfigureAwait(false); 17 progress.Report(i); 18 19 } 20 }
3.自定义Myprocess
1 using System.Numerics; 2 3 class MyProgress<T> : Progress<T> where T : notnull 4 { 5 private readonly Action? _complete; 6 private readonly T _maximum; 7 private bool _isCompleted; 8 9 public MyProgress(Action<T> handler, Action? complete, T maximum) 10 : base(handler) 11 { 12 _complete = complete; 13 _maximum = maximum; 14 ProgressChanged += CheckCompletion; 15 16 } 17 18 protected override void OnReport(T value) 19 { 20 if (_isCompleted) return; 21 base.OnReport(value); 22 } 23 24 25 private void CheckCompletion(object? sender, T e) 26 { 27 if (e.Equals(_maximum) && !_isCompleted) 28 _isCompleted = true; 29 _complete?.Invoke(); 30 } 31 32 }
调用:
1 private async void button4_Click(object sender, EventArgs e) 2 { 3 button4.Enabled = false; 4 var progress = new MyProgress<double>(value => progressBar1.Value = (int)value, () => 5 { 6 button4.Enabled = true; 7 },100); 8 await Dojob(progress); 9 10 11 }