winform開發(fā)使用通用多線程基類分享(以隊列形式)
/// <summary>
/// 隊列多線程,T 代表處理的單個類型~
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class QueueThreadBase<T>
{
#region 變量&屬性
/// <summary>
/// 待處理結(jié)果
/// </summary>
private class PendingResult
{
/// <summary>
/// 待處理值
/// </summary>
public T PendingValue { get; set; }
/// <summary>
/// 是否有值
/// </summary>
public bool IsHad { get; set; }
}
/// <summary>
/// 線程數(shù)
/// </summary>
public int ThreadCount
{
get { return this.m_ThreadCount; }
set { this.m_ThreadCount = value; }
}
private int m_ThreadCount = 5;
/// <summary>
/// 取消=True
/// </summary>
public bool Cancel { get; set; }
/// <summary>
/// 線程列表
/// </summary>
List<Thread> m_ThreadList;
/// <summary>
/// 完成隊列個數(shù)
/// </summary>
private volatile int m_CompletedCount = 0;
/// <summary>
/// 隊列總數(shù)
/// </summary>
private int m_QueueCount = 0;
/// <summary>
/// 全部完成鎖
/// </summary>
private object m_AllCompletedLock = new object();
/// <summary>
/// 完成的線程數(shù)
/// </summary>
private int m_CompetedCount = 0;
/// <summary>
/// 隊列鎖
/// </summary>
private object m_PendingQueueLock = new object();
private Queue<T> m_InnerQueue;
#endregion
#region 事件相關(guān)
/// <summary>
/// 全部完成事件
/// </summary>
public event Action<CompetedEventArgs> AllCompleted;
/// <summary>
/// 單個完成事件
/// </summary>
public event Action<T, CompetedEventArgs> OneCompleted;
/// <summary>
/// 引發(fā)全部完成事件
/// </summary>
/// <param name="args"></param>
private void OnAllCompleted(CompetedEventArgs args)
{
if (AllCompleted != null)
{
try
{
AllCompleted(args);//全部完成事件
}
catch { }
}
}
/// <summary>
/// 引發(fā)單個完成事件
/// </summary>
/// <param name="pendingValue"></param>
/// <param name="args"></param>
private void OnOneCompleted(T pendingValue, CompetedEventArgs args)
{
if (OneCompleted != null)
{
try
{
OneCompleted(pendingValue, args);
}
catch { }
}
}
#endregion
#region 構(gòu)造
public QueueThreadBase(IEnumerable<T> collection)
{
m_InnerQueue = new Queue<T>(collection);
this.m_QueueCount = m_InnerQueue.Count;
}
#endregion
#region 主體
/// <summary>
/// 初始化線程
/// </summary>
private void InitThread()
{
m_ThreadList = new List<Thread>();
for (int i = 0; i < ThreadCount; i++)
{
Thread t = new Thread(new ThreadStart(InnerDoWork));
m_ThreadList.Add(t);
t.IsBackground = true;
t.Start();
}
}
/// <summary>
/// 開始
/// </summary>
public void Start()
{
InitThread();
}
/// <summary>
/// 線程工作
/// </summary>
private void InnerDoWork()
{
try
{
Exception doWorkEx = null;
DoWorkResult doworkResult = DoWorkResult.ContinueThread;
var t = CurrentPendingQueue;
while (!this.Cancel && t.IsHad)
{
try
{
doworkResult = DoWork(t.PendingValue);
}
catch (Exception ex)
{
doWorkEx = ex;
}
m_CompletedCount++;
int precent = m_CompletedCount * 100 / m_QueueCount;
OnOneCompleted(t.PendingValue, new CompetedEventArgs() { CompetedPrecent = precent, InnerException = doWorkEx });
if (doworkResult == DoWorkResult.AbortAllThread)
{
this.Cancel = true;
break;
}
else if (doworkResult == DoWorkResult.AbortCurrentThread)
{
break;
}
t = CurrentPendingQueue;
}
lock (m_AllCompletedLock)
{
m_CompetedCount++;
if (m_CompetedCount == m_ThreadList.Count)
{
OnAllCompleted(new CompetedEventArgs() { CompetedPrecent = 100 });
}
}
}
catch
{
throw;
}
}
/// <summary>
/// 子類重寫
/// </summary>
/// <param name="pendingValue"></param>
/// <returns></returns>
protected virtual DoWorkResult DoWork(T pendingValue)
{
return DoWorkResult.ContinueThread;
}
/// <summary>
/// 獲取當(dāng)前結(jié)果
/// </summary>
private PendingResult CurrentPendingQueue
{
get
{
lock (m_PendingQueueLock)
{
PendingResult t = new PendingResult();
if (m_InnerQueue.Count != 0)
{
t.PendingValue = m_InnerQueue.Dequeue();
t.IsHad = true;
}
else
{
t.PendingValue = default(T);
t.IsHad = false;
}
return t;
}
}
}
#endregion
#region 相關(guān)類&枚舉
/// <summary>
/// dowork結(jié)果枚舉
/// </summary>
public enum DoWorkResult
{
/// <summary>
/// 繼續(xù)運行,默認(rèn)
/// </summary>
ContinueThread = 0,
/// <summary>
/// 終止當(dāng)前線程
/// </summary>
AbortCurrentThread = 1,
/// <summary>
/// 終止全部線程
/// </summary>
AbortAllThread = 2
}
/// <summary>
/// 完成事件數(shù)據(jù)
/// </summary>
public class CompetedEventArgs : EventArgs
{
public CompetedEventArgs()
{
}
/// <summary>
/// 完成百分率
/// </summary>
public int CompetedPrecent { get; set; }
/// <summary>
/// 異常信息
/// </summary>
public Exception InnerException { get; set; }
}
#endregion
}
1.從構(gòu)造函數(shù)來看,處理的是一個確定的列表.沒錯.這個多線程只能處理已經(jīng)確定的列表,你是否會問.可不可以一邊添加,一邊處理呢?(呵呵,可以,請聯(lián)系樓主,當(dāng)然你也可以自己寫,是吧?!)
public QueueThreadBase(IEnumerable<T> collection)
2.提供撤銷的功能
/// <summary>
/// 取消=True
/// </summary>
public bool Cancel { get; set; }
3.提供線程個數(shù)修改功能
/// <summary>
/// 線程數(shù)
/// </summary>
public int ThreadCount
{
get { return this.m_ThreadCount; }
set { this.m_ThreadCount = value; }
}
4.提供多種事件響應(yīng),如單個完成,全部完成的事件
/// <summary>
/// 全部完成事件
/// </summary>
public event Action<CompetedEventArgs> AllCompleted;
/// <summary>
/// 單個完成事件
/// </summary>
public event Action<T, CompetedEventArgs> OneCompleted;
5.提供完成的百分率
/// <summary>
/// 完成事件數(shù)據(jù)
/// </summary>
public class CompetedEventArgs : EventArgs
{
public CompetedEventArgs()
{
}
/// <summary>
/// 完成百分率
/// </summary>
public int CompetedPrecent { get; set; }
/// <summary>
/// 異常信息
/// </summary>
public Exception InnerException { get; set; }
}
6.提供終止線程的方式,繼續(xù)/單線程終止/全部終止
/// <summary>
/// dowork結(jié)果枚舉
/// </summary>
public enum DoWorkResult
{
/// <summary>
/// 繼續(xù)運行,默認(rèn)
/// </summary>
ContinueThread = 0,
/// <summary>
/// 終止當(dāng)前線程
/// </summary>
AbortCurrentThread = 1,
/// <summary>
/// 終止全部線程
/// </summary>
AbortAllThread = 2
}
你是否會問?怎么用呢?別急....請看
/// <summary>
/// 下載線程對了.
/// </summary>
public class DownLoadQueueThread:QueueThreadBase<int>
{
/// <summary>
///
/// </summary>
/// <param name="list">下載的列表ID</param>
public DownLoadQueueThread(IEnumerable<int> list):base(list)
{
}
/// <summary>
/// 每次多線程都到這里來,處理多線程
/// </summary>
/// <param name="pendingValue"列表ID></param>
/// <returns></returns>
protected override DoWorkResult DoWork(int pendingID)
{
try
{
//..........多線程處理....
return DoWorkResult.ContinueThread;//沒有異常讓線程繼續(xù)跑..
}
catch (Exception)
{
return DoWorkResult.AbortCurrentThread;//有異常,可以終止當(dāng)前線程.當(dāng)然.也可以繼續(xù),
//return DoWorkResult.AbortAllThread; //特殊情況下 ,有異常終止所有的線程...
}
//return base.DoWork(pendingValue);
}
}
用法
總結(jié):
多線程在什么時候都會用到.不用到是你不會用.多線程要一定的編程基礎(chǔ),如果你覺得有點難度,那你可以學(xué)習(xí)并且借鑒人家已有的東西.少走彎路,是我們程序員經(jīng)歷嗷嗷待哺后的心聲.本文以交流態(tài)度和感恩心態(tài),貢獻(xiàn)給有需要的人們.
相關(guān)文章
C#數(shù)據(jù)類型轉(zhuǎn)換(顯式轉(zhuǎn)型、隱式轉(zhuǎn)型、強制轉(zhuǎn)型)
本文詳細(xì)講解了C#數(shù)據(jù)類型轉(zhuǎn)換(顯式轉(zhuǎn)型、隱式轉(zhuǎn)型、強制轉(zhuǎn)型),文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-01-01C#異步迭代IAsyncEnumerable應(yīng)用實現(xiàn)
IAsyncEnumerable可以來實現(xiàn)異步迭代,本文就主要介紹了C#異步迭代IAsyncEnumerable應(yīng)用實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06