自动化一定离不开异步执行,异步的概念相对于同步,异步的实现方式是多线程。多线程就是通过CPU分配时间段来执行每个线程。
1.BeginInvoke 应用于winform上修改UI
/*
Control.BeginInvoke 方法定义
命名空间:System.Windows.Forms
程序集:System.Windows.Forms.dll
在创建控件的基础句柄所在线程上异步执行委托。
public IAsyncResult BeginInvoke (Delegate method);
官网:https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.forms.control.begininvoke?view=netframework-4.0
*/
//例 1:
public delegate void InvokeDelegate();//定义一个委托
private void Invoke_Click(object sender, EventArgs e)
{
myTextBox.BeginInvoke(new InvokeDelegate(InvokeMethod));//调用委托
}
public void InvokeMethod()
{
myTextBox.Text = "Executed the given delegate";//可以异步修改
}
//例 2:
BeginInvoke(new Action(() =>
{
for (int i = 0; i < lDGV.Count; i++)
{
lDGV[i].TopLeftHeaderCell.Style.BackColor = Color.Gray;
}
btn.Text = "开始";
pubFun.SetConfig("frmMain", "Running", "0");
}));
//Action 是系统的无参委托
//例 3: 重载带参数
BeginInvoke(new InvokeEvent(frmMain.comDatas.ShowDatas), new object[] { new InvokeEventArgs { Event = "COMDATA", Type = 1, MSG = port.PortName + "收:" + oRcv + "\r\n解析结果:" + sRst } });
public void ShowDatas(InvokeEventArgs ie)
{
lock (lockOb)
{
int nMaxL = 300;
if (!int.TryParse(tMaxLine.Text, out nMaxL))
{
nMaxL = 300;
}
if (rtComInfo.Lines.Length > nMaxL)
{
rtComInfo.Text = "";
}
rtComInfo.SelectionStart = rtComInfo.Text.Length;
switch (ie.Event)
{
case "COMDATA":
rtComInfo.SelectionStart = rtComInfo.Text.Length;
switch (ie.Type)
{
case 0:
rtComInfo.SelectionColor = Color.Green;
rtComInfo.AppendText(System.DateTime.Now.ToString("HH:mm:ss.fff") + " " + ie.MSG + "\r\n");
break;
case 1:
rtComInfo.SelectionColor = Color.Gold;
rtComInfo.AppendText(System.DateTime.Now.ToString("HH:mm:ss.fff") + " " + ie.MSG + "\r\n");
break;
}
break;
}
this.rtComInfo.ScrollToCaret();
}
}
// InvokeEventArgs 参数对象
public class InvokeEventArgs : EventArgs
{
public string Event { get; set; }
public string MSG { get; set; }
public bool Result { get; set; }
public int Type { get; set; }
public int RowIndex { get; set; }
public int ColumnIndex { get; set; }
}
2.BackgroundWorker 可以在单独的线程上进行操作
/*
BackgroundWorker 类定义
命名空间:System.ComponentModel
程序集:System.dll
在单独的线程上执行操作。
https://docs.microsoft.com/zh-cn/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.0
BackgroundWorker类允许您在单独的专用线程上运行操作。 耗时的操作(如下载和数据库事务)可能导致用户界面 (UI) 在运行时已停止响应。 如果需要响应式 UI,并面临与此类操作相关联的长时间延迟,此 BackgroundWorker 类提供了一个方便的解决方案。
若要在后台执行耗时的操作,请创建 BackgroundWorker 并侦听报告操作进度的事件,并在操作完成后发出信号。 可以 BackgroundWorker 通过编程方式创建,也可以从 "工具箱" 的 "组件" 选项卡将其拖到窗体上。 如果 BackgroundWorker 在 Windows 窗体设计器中创建,它将显示在组件栏中,并且它的属性将显示在属性窗口中。
若要设置后台操作,请为事件添加事件处理程序 DoWork 。 在此事件处理程序中调用耗时的操作。 若要开始操作,请调用 RunWorkerAsync 。 若要接收有关进度更新的通知,请处理 ProgressChanged 事件。 若要在操作完成时接收通知,请处理 RunWorkerCompleted 事件。
*/
//创建
BackgroundWorker bgwIO = new BackgroundWorker();
//绑定
bgwIO.DoWork += new DoWorkEventHandler(bgwIO_DoWork);
//触发
bgwIO.RunWorkerAsync(new object[] { comIO });
//执行
void bgwIO_DoWork(object sender, DoWorkEventArgs e)
{
object[] args = e.Argument as object[];//获取参数
string portName = args[0].ToString();
.......
}
3. AutoResetEvent 用于线程的同步
/*
命名空间:System.Threading
程序集:mscorlib.dll
表示线程同步事件在一个等待线程释放后收到信号时自动重置。 此类不能被继承。
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.autoresetevent?view=netframework-4.0
*/
4. Task
/*
命名空间: System.Threading.Tasks
程序集: mscorlib.dll
表示一个异步操作。
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task?view=netframework-4.0
*/
Task task = new Task(() =>
{
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
5. Parallel
/*
Parallel 类定义
命名空间:System.Threading.Tasks
程序集:mscorlib.dll
提供对并行循环和区域的支持。
https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.parallel?view=netframework-4.0
*/
//例
Parallel.For(0, readers.Length, i =>//财哥:2021/01/25 09:00:54 同时运行两个设备。由i来区别 0是起始 readers.Length变量的值是终止
{
bw_DoWork(null, new DoWorkEventArgs(new object[] { i }));
});
void bw_DoWork(object sender, DoWorkEventArgs e)
{
object[] obs = e.Argument as object[];
int rnIndex = Convert.ToInt32(obs[0]);
Console.WriteLine(rnIndex);
............
}