如果在WinForm中执行一个长时间操作时,窗体就会被锁死,直到操作完成,对于操作者的体验就是死锁状态,那在.NET(.net 5以后)中,怎么实现一个并发,等待,且同步操作信息窗口呢?
第一步:首先定义一个等待窗体,为了有明确的提示,做一个等待的gif图,同步有提示信息。.
partial class LoadingForm{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoadingForm));pictureBox1 = new PictureBox();messageLab = new Label();((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();SuspendLayout();//// pictureBox1//pictureBox1.BackColor = Color.White;pictureBox1.Dock = DockStyle.Top;pictureBox1.Image = (Image)resources.GetObject("pictureBox1.Image");pictureBox1.Location = new Point(0, 0);pictureBox1.Name = "pictureBox1";pictureBox1.Size = new Size(647, 141);pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;pictureBox1.TabIndex = 0;pictureBox1.TabStop = false;//// messageLab//messageLab.BackColor = Color.Azure;messageLab.Dock = DockStyle.Fill;messageLab.Font = new Font("Microsoft YaHei UI", 12F, FontStyle.Bold, GraphicsUnit.Point);messageLab.Location = new Point(0, 141);messageLab.Name = "messageLab";messageLab.Padding = new Padding(30, 40, 30, 5);messageLab.Size = new Size(647, 153);messageLab.TabIndex = 1;messageLab.Text = "正在加载中,请等待……";//// LoadingForm//AutoScaleDimensions = new SizeF(7F, 17F);AutoScaleMode = AutoScaleMode.Font;ClientSize = new Size(647, 294);Controls.Add(messageLab);Controls.Add(pictureBox1);Name = "LoadingForm";ShowIcon = false;ShowInTaskbar = false;StartPosition = FormStartPosition.CenterScreen;Text = "Loading";TopMost = true;((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();ResumeLayout(false);}#endregionprivate PictureBox pictureBox1;private Label messageLab;}
public partial class LoadingForm : Form{public LoadingForm(){InitializeComponent();this.FormBorderStyle = FormBorderStyle.None;}public string Message{set{this.Invoke(() =>{messageLab.Text = value;});}}public void CloseAll(){this.Invoke(() =>{this.Close();this.Dispose();});}}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace WaitForm{public static class LoadingManage{static LoadingForm _loading;public static void Show(){Task.Run(() =>{_loading = new LoadingForm();_loading.ShowDialog();});}public static void Close(){Task.Run(() =>{while (_loading == null || _loading.IsDisposed){Thread.Sleep(10);}_loading.CloseAll();});}public static string Message{set{while (_loading == null||_loading.IsDisposed){Thread.Sleep(10);}Task.Run(() =>{_loading.Message = value;});}}}}
封装后,调用就简单了,如下,首先Show(),然后执行密集服务,在执行过程中,可以更新Message属性,最后执行完就可以Close()了。
LoadingManage.Show();for (var i = 0; i < 3; i++){LoadingManage.Message = $"正在执行第{i}条数据……";Thread.Sleep(1000);}LoadingManage.Close();
下面是准备果图:
