C#   发布时间:2022-04-13  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了C# Task异步任务大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

 Task用的是线程池,线程池的线程数量的有上限的,这个可以通过ThreadPool修改,我们经常会用到task.run ,new task ,和task.factory.startnew方法来创建任务@H_618_1@

Task.Factory.StartNew(action)不是直接创建线程,创建的是任务,它有一个任务队列,然后通过任务调度器把任务分配到线程池中的空闲线程中,任务是不能被直接执行的,只有分配给线程才能被执行,如果任务的数量比线程池中的线程多,线程池的线程数量还没有到达上限,就会创建新线程执行任务。如果线程池的线程已到达上限,没有分配到线程的任务需要等待有线程空闲的时候才执行。@H_618_1@

task 是新建一个异步任务,这个任务是分配到子线程中去的,跟我们之前的new thread,创建线程很相似,在子线程中,通过SynchronizationContext类进行上下文同步,实现子线程和主线程之间的通信。@H_618_1@

ConTinueWith:创建一个在目标 Task 完成时异步执行的延续任务,也就是Task完成后要执行的任务@H_618_1@

示例代码如下:@H_618_1@

Task.Factory.StartNew(() =>
{
AddDr("SELEct s_FilePathName from T_Files where isnull(s_FilePathName,'') <>''");
}).ConTinueWith(i =>
{
this.Invoke(new Action(delegate
{
lblProcess.Text = "数据库文件记录读取完成,共" + dt.Rows.Count + "个,开始执行复制...";
//读取完成后,开始copy file @H_618_1@

}));
});@H_618_1@

task 和 thread ,以及thread pool区别:
Task是将多个操作封装成一个概念上原子操作。但这个操作由哪个Thread甚至多个Thread来处理处理你并不清楚。总之就是可以被正常完成。
Thread仅仅是一条线程,所有操作都是这个Thread一个完成的。@H_618_1@

thread是单核多线程,task是多核多线程@H_618_1@

task 比thread pool 线程池优越的地方在于,在thread pool时期,我们不能知道一个workitem是否完成,也不能在完成后知道workitem所得出的返回值,task封装后解决了这个问题,并且可以清楚地知道返回值。@H_618_1@

附上我自己写的一个文件复制的小demo代码:@H_618_1@

运行效果:@H_618_1@

C# Task异步任务@H_618_1@@H_618_1@

 @H_618_1@

 @H_618_1@

代码如下:@H_618_1@

----------------------------------------------------------------------------------------------------@H_618_1@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;@H_618_1@

namespace CopyFiles
{
public partial class Form1 : Form
{
delegate void AsynupdateUI(int step);@H_618_1@

public Form1()
{
InitializeComponent();
}@H_618_1@

private void button1_Click(object sender, EventArgs E)
{
SqlConnection con = new SqlConnection(String.Format("server={0};database={1};user={2};pwd={3};", txtServer.Text, txtDB.Text, txtSa.Text, txtPwd.Text));
try
{
//2. 数据库操作类 关键字SqlCommand
SqlCommand cm = con.CreateCommand();@H_618_1@

//编写Tsql语
cm.CommandText = "SELEct count(*) from TCase_Base";@H_618_1@

//3. 数据库连接通道开启
//上面只是连接到了数据库,并获取到了数据库的表的信息,需要开启才能实现操作
con.open();//开启@H_618_1@

//4. 数据读取类 关键字SqlDataReader
SqlDataReader dq = cm.ExecuteReader();//读取一下获取到的数据库数据
if (dq.HasRows) //if判断是否能够读取到数据库,读取到了走里面程序,读取不到说明有错误
{
while (dq.Read())//每次只读取一条数据,加个循环,将每条数据循环读取出来,每读到一条数据返回的是true类型,当没有数据的时候是false类型,自动结束循环
{
if (dq[0] != DBNull.value)
{@H_618_1@

}
}
}
messageBox.Show("测试连接成功!");
}
catch (Exception eX)
{
messageBox.Show("测试连接失败!" + ex.messagE);
}
finally
{
con.Close();//使用完之后关闭数据库连接
}
}@H_618_1@

private void button2_Click(object sender, EventArgs E)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.Description = "请选择源文件目录";@H_618_1@

if (dialog.ShowDialog() == DialogResult.oK)
{
txtYFile.Text = dialog.SELEctedPath;
}
}@H_618_1@

private void button3_Click(object sender, EventArgs E)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.Description = "请选择目标文件目录";@H_618_1@

if (dialog.ShowDialog() == DialogResult.oK)
{
txtTFile.Text = dialog.SELEctedPath;
}
}@H_618_1@

private DataTable dt;
private void button4_Click(object sender, EventArgs E)
{
if (txtYFile.Text == "" && txtTFile.Text == "")
{
messageBox.Show("源文件目录、目标文件目录不能为空!");
return;
}
failList = new List<String>();
this.button4.Enabled = false;
dt = new DataTable();
dt.columns.Add("filepath", typeof(String));
Task.Factory.StartNew(() =>
{
AddDr("SELEct s_FilePathName from TFiles where isnull(s_FilePathName,'') <>''");
AddDr("SELEct s_EmailPath from TEmail where isnull(s_EmailPath,'') <>''");
}).ConTinueWith(i =>
{
this.Invoke(new Action(delegate
{
lblProcess.Text = "数据库文件记录读取完成,共" + dt.Rows.Count + "个,开始执行复制...";
//读取完成后,开始copy file
int taskCount = dt.Rows.Count;
this.pgbWrite.Maximum = taskCount;
this.pgbWrite.Value = 0;@H_618_1@

updateUIDelegate += updataUIStatus;//绑定更新任务状态的委托
TaskCallBACk += Accomplish;//绑定完成任务要调用的委托@H_618_1@

Thread thread = new Thread(WritE);
thread.IsBACkground = true;
thread.Start();
}));
});@H_618_1@


}@H_618_1@

private void AddDr(String sql)
{
SqlConnection con = new SqlConnection(String.Format("server={0};database={1};user={2};pwd={3};", txtServer.Text, txtDB.Text, txtSa.Text, txtPwd.Text));
try
{
SqlCommand cm = con.CreateCommand();
cm.CommandText = sql;
con.open();
SqlDataReader dq = cm.ExecuteReader();
if (dq.HasRows)
{
while (dq.Read())
{
if (dq[0] != DBNull.Value && dq[0].ToString() != "")
{
DataRow dataRow = dt.NewRow();
dataRow["filepath"] = dq[0].ToString();
dt.Rows.Add(dataRow);
}
}
}
}
catch (Exception eX)
{
messageBox.Show(ex.messagE);
}
finally
{
con.Close();//使用完之后关闭数据库连接
}
}@H_618_1@

private void updataUIStatus(int step)
{
if (Invokerequired)
{
this.Invoke(new AsynupdateUI(delegate(int s)
{
this.pgbWrite.Value += s;
this.lblProcess.Text = "共" + dt.Rows.Count + "个,正在执行第" + this.pgbWrite.Value.ToString() + "个";
}), step);
}
else
{
this.pgbWrite.Value += step;
this.lblProcess.Text = "共" + dt.Rows.Count + "个,正在执行第" + this.pgbWrite.Value.ToString() + "个";
}
}@H_618_1@

private void Accomplish()
{
//还可以进行其他的一些完任务完成之后的逻辑处理
if (Invokerequired)
{
this.Invoke(new AsynupdateUI(delegate(int s)
{
lblProcess.Text = "执行完成,共" + dt.Rows.Count + "个," + success + "个成功," + fail + "个失败," + noFile + "个不存在";
File.WriteAllLines(Application.StartupPath+"\\失败的文件记录.txt", failList);
}), 0);
}
else
{@H_618_1@

lblProcess.Text = "执行完成,共" + dt.Rows.Count + "个," + success + "个成功," + fail + "个失败," + noFile + "个不存在";
File.WriteAllLines(Application.StartupPath + "\\失败的文件记录.txt", failList);
}
}@H_618_1@

public delegate void updateUI(int step);//声明一个更新主线程的委托
public updateUI updateUIDelegate;@H_618_1@

public delegate void AccomplishTask();//声明一个在完成任务时通知主线程的委托
public AccomplishTask TaskCallBACk;
privatE int success;
privatE int fail;
private int noFile;
private List<String> failList;
public void Write()
{
foreach (DataRow dr in dt.Rows)
{
String yFile = txtYFile.Text + "\\" + dr["filepath"].ToString();
if (File.Exists(yFilE))
{
String tFile = txtTFile.Text + "\\" + dr["filepath"].ToString();
String outmsg;
if (CopyFile(yFile, tFile, true, out outmsg))
{
success++;
}
else
{
failList.Add(yFilE);
fail++;
}
}
else
{
noFile++;
}@H_618_1@

//写入一条数据,调用更新主线程ui状态的委托
updateUIDelegate(1);
}
//任务完成时通知主线程作出相应的处理
TaskCallBACk();
//将更新包信息写入到客户端文件配置中
Thread.Sleep(1000);
}@H_618_1@

public static bool CopyFile(String ssource, String sTarget, bool bOverride, out String errormessagE)
{
errormessage = null;@H_618_1@

try
{
if (!Directory.Exists(Path.GetDirectoryName(sTarget)))
{ // 如果目标路径不存在,则创建目标路径
Directory.CreateDirectory(Path.GetDirectoryName(sTarget));
}
//如果目标文件已存在,先将其设为非只读
SetFileReadOnly(sTarget, falsE);
File.Copy(ssource, sTarget, bOverridE);
//保存后再次设为非只读
SetFileReadOnly(sTarget, falsE);
return true;
}
catch (Exception eX)
{
errormessage = ex.message;
return false;
}
}@H_618_1@

public static bool SetFileReadOnly(String sPath, bool bReadOnly)
{
if (File.Exists(sPath) == falsE)
{
return false;
}
try
{
FileInfo fileInfo = new FileInfo(sPath);@H_618_1@

if (fileInfo.Attributes.ToString().IndexOf("ReadOnly") != -1)@H_618_1@

fileInfo.Attributes = bReadOnly ? FileAttributes.ReadOnly : FileAttributes.Normal;
}
catch (Exception eX)
{
return false;
}@H_618_1@

return true;@H_618_1@

}@H_618_1@

}
}@H_618_1@

大佬总结

以上是大佬教程为你收集整理的C# Task异步任务全部内容,希望文章能够帮你解决C# Task异步任务所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: