Task用的是執行緒池,執行緒池的執行緒數量的有上限的,這個可以通過ThreadPool修改,我們經常會用到task.run ,new task ,和task.factory.startnew方法來創建任務
Task.Factory.StartNew(action)不是直接創建執行緒,創建的是任務,它有一個任務佇列,然后通過任務調度器把任務分配到執行緒池中的空閑執行緒中,任務是不能被直接執行的,只有分配給執行緒才能被執行,如果任務的數量比執行緒池中的執行緒多,執行緒池的執行緒數量還沒有到達上限,就會創建新執行緒執行任務,如果執行緒池的執行緒已到達上限,沒有分配到執行緒的任務需要等待有執行緒空閑的時候才執行,
task 是新建一個異步任務,這個任務是分配到子執行緒中去的,跟我們之前的new thread,創建執行緒很相似,在子執行緒中,通過SynchronizationContext類進行背景關系同步,實作子執行緒和主執行緒之間的通信,
ContinueWith:創建一個在目標 Task 完成時異步執行的延續任務,也就是Task完成后要執行的任務
示例代碼如下:
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
}));
});
task 和 thread ,以及thread pool區別:
Task是將多個操作封裝成一個概念上原子操作,但這個操作由哪個Thread甚至多個Thread來處理處理你并不清楚,總之就是可以被正常完成,
Thread僅僅是一條執行緒,所有操作都是這個Thread一個完成的,
thread是單核多執行緒,task是多核多執行緒
task 比thread pool 執行緒池優越的地方在于,在thread pool時期,我們不能知道一個workitem是否完成,也不能在完成后知道workitem所得出的回傳值,task封裝后解決了這個問題,并且可以清楚地知道回傳值,
附上我自己寫的一個檔案復制的小demo代碼:
運行效果:

代碼如下:
----------------------------------------------------------------------------------------------------
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;
namespace CopyFiles
{
public partial class Form1 : Form
{
delegate void AsynUpdateUI(int step);
public Form1()
{
InitializeComponent();
}
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();
//撰寫TSQL陳述句
cm.CommandText = "select count(*) from TCase_Base";
//3. 資料庫連接通道開啟
//上面只是連接到了資料庫,并獲取到了資料庫的表的資訊,需要開啟才能實作操作
con.Open();//開啟
//4. 資料讀取類 關鍵字SqlDataReader
SqlDataReader dq = cm.ExecuteReader();//讀取一下獲取到的資料庫資料
if (dq.HasRows) //if判斷是否能夠讀取到資料庫,讀取到了走里面程式,讀取不到說明有錯誤
{
while (dq.Read())//每次只讀取一條資料,加個回圈,將每條資料回圈讀取出來,每讀到一條資料回傳的是true型別,當沒有資料的時候是false型別,自動結束回圈
{
if (dq[0] != DBNull.Value)
{
}
}
}
MessageBox.Show("測驗連接成功!");
}
catch (Exception ex)
{
MessageBox.Show("測驗連接失敗!" + ex.Message);
}
finally
{
con.Close();//使用完之后關閉資料庫連接
}
}
private void button2_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.Description = "請選擇源檔案目錄";
if (dialog.ShowDialog() == DialogResult.OK)
{
txtYFile.Text = dialog.SelectedPath;
}
}
private void button3_Click(object sender, EventArgs e)
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.Description = "請選擇目標檔案目錄";
if (dialog.ShowDialog() == DialogResult.OK)
{
txtTFile.Text = dialog.SelectedPath;
}
}
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 = https://www.cnblogs.com/lihaishu/p/0;
UpdateUIDelegate += UpdataUIStatus;//系結更新任務狀態的委托
TaskCallBack += Accomplish;//系結完成任務要呼叫的委托
Thread thread = new Thread(Write);
thread.IsBackground = true;
thread.Start();
}));
});
}
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();//使用完之后關閉資料庫連接
}
}
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() + "個";
}
}
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
{
lblProcess.Text = "執行完成,共" + dt.Rows.Count + "個," + success + "個成功," + fail + "個失敗," + noFile + "個不存在";
File.WriteAllLines(Application.StartupPath + "\\失敗的檔案記錄.txt", failList);
}
}
public delegate void UpdateUI(int step);//宣告一個更新主執行緒的委托
public UpdateUI UpdateUIDelegate;
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++;
}
//寫入一條資料,呼叫更新主執行緒ui狀態的委托
UpdateUIDelegate(1);
}
//任務完成時通知主執行緒作出相應的處理
TaskCallBack();
//將更新包資訊寫入到客戶端檔案配置中
Thread.Sleep(1000);
}
public static bool CopyFile(string sSource, string sTarget, bool bOverride, out string errorMessage)
{
errorMessage = null;
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;
}
}
public static bool SetFileReadOnly(string sPath, bool bReadOnly)
{
if (File.Exists(sPath) == false)
{
return false;
}
try
{
FileInfo fileInfo = new FileInfo(sPath);
if (fileInfo.Attributes.ToString().IndexOf("ReadOnly") != -1)
fileInfo.Attributes = bReadOnly ? FileAttributes.ReadOnly : FileAttributes.Normal;
}
catch (Exception ex)
{
return false;
}
return true;
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/453711.html
標籤:C#
