winform开发使用通用多线程基类分享(以队列形式)
发布时间:2023-05-26 14:22:27
/// <summary>
/// 队列多线程,T 代表处理的单个类型~
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class QueueThreadBase<T>
{
#region 变量&属性
/// <summary>
/// 待处理结果
/// </summary>
private class PendingResult
{
/// <summary>
/// 待处理值
/// </summary>
public T PendingValue { get; set; }
/// <summary>
/// 是否有值
/// </summary>
public bool IsHad { get; set; }
}
/// <summary>
/// 线程数
/// </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>
/// 完成队列个数
/// </summary>
private volatile int m_CompletedCount = 0;
/// <summary>
/// 队列总数
/// </summary>
private int m_QueueCount = 0;
/// <summary>
/// 全部完成锁
/// </summary>
private object m_AllCompletedLock = new object();
/// <summary>
/// 完成的线程数
/// </summary>
private int m_CompetedCount = 0;
/// <summary>
/// 队列锁
/// </summary>
private object m_PendingQueueLock = new object();
private Queue<T> m_InnerQueue;
#endregion
#region 事件相关
/// <summary>
/// 全部完成事件
/// </summary>
public event Action<CompetedEventArgs> AllCompleted;
/// <summary>
/// 单个完成事件
/// </summary>
public event Action<T, CompetedEventArgs> OneCompleted;
/// <summary>
/// 引发全部完成事件
/// </summary>
/// <param name="args"></param>
private void OnAllCompleted(CompetedEventArgs args)
{
if (AllCompleted != null)
{
try
{
AllCompleted(args);//全部完成事件
}
catch { }
}
}
/// <summary>
/// 引发单个完成事件
/// </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 构造
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>
/// 获取当前结果
/// </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 相关类&枚举
/// <summary>
/// dowork结果枚举
/// </summary>
public enum DoWorkResult
{
/// <summary>
/// 继续运行,默认
/// </summary>
ContinueThread = 0,
/// <summary>
/// 终止当前线程
/// </summary>
AbortCurrentThread = 1,
/// <summary>
/// 终止全部线程
/// </summary>
AbortAllThread = 2
}
/// <summary>
/// 完成事件数据
/// </summary>
public class CompetedEventArgs : EventArgs
{
public CompetedEventArgs()
{
}
/// <summary>
/// 完成百分率
/// </summary>
public int CompetedPrecent { get; set; }
/// <summary>
/// 异常信息
/// </summary>
public Exception InnerException { get; set; }
}
#endregion
}
1.从构造函数来看,处理的是一个确定的列表.没错.这个多线程只能处理已经确定的列表,你是否会问.可不可以一边添加,一边处理呢?(呵呵,可以,请联系楼主,当然你也可以自己写,是吧?!)
public QueueThreadBase(IEnumerable<T> collection)
2.提供撤销的功能
/// <summary>
/// 取消=True
/// </summary>
public bool Cancel { get; set; }
3.提供线程个数修改功能
/// <summary>
/// 线程数
/// </summary>
public int ThreadCount
{
get { return this.m_ThreadCount; }
set { this.m_ThreadCount = value; }
}
4.提供多种事件响应,如单个完成,全部完成的事件
/// <summary>
/// 全部完成事件
/// </summary>
public event Action<CompetedEventArgs> AllCompleted;
/// <summary>
/// 单个完成事件
/// </summary>
public event Action<T, CompetedEventArgs> OneCompleted;
5.提供完成的百分率
/// <summary>
/// 完成事件数据
/// </summary>
public class CompetedEventArgs : EventArgs
{
public CompetedEventArgs()
{
}
/// <summary>
/// 完成百分率
/// </summary>
public int CompetedPrecent { get; set; }
/// <summary>
/// 异常信息
/// </summary>
public Exception InnerException { get; set; }
}
6.提供终止线程的方式,继续/单线程终止/全部终止
/// <summary>
/// dowork结果枚举
/// </summary>
public enum DoWorkResult
{
/// <summary>
/// 继续运行,默认
/// </summary>
ContinueThread = 0,
/// <summary>
/// 终止当前线程
/// </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;//没有异常让线程继续跑..
}
catch (Exception)
{
return DoWorkResult.AbortCurrentThread;//有异常,可以终止当前线程.当然.也可以继续,
//return DoWorkResult.AbortAllThread; //特殊情况下 ,有异常终止所有的线程...
}
//return base.DoWork(pendingValue);
}
}
用法
总结:
多线程在什么时候都会用到.不用到是你不会用.多线程要一定的编程基础,如果你觉得有点难度,那你可以学习并且借鉴人家已有的东西.少走弯路,是我们程序员经历嗷嗷待哺后的心声.本文以交流态度和感恩心态,贡献给有需要的人们.


猜你喜欢
- 本文为大家分享了java多线程的简单实现及线程池实例,供大家参考,具体内容如下一、多线程的两种实现方式1、继承Thread类的多线程/**
- 1: Nacos搭建可以参考 https://www.jb51.net/article/196842.htmSpringCloud 版本&l
- config.json 文件内容如下{"Data": {"DefaultConnection": {
- Flutter中的生命周期类似于Vue、React中的生命周期一样,有初始化、状态更新、停用、销毁等。在React中,组件分为函数式组件和类
- @property可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,但是有时候setter/deleter也是需要的。
- 在[高并发Java 二] 多线程基础中,我们已经初步提到了基本的线程同步操作。这次要提到的是在并发包中的同步控制工具。1. 各种同步控制工具
- 排序算法介绍排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程。排序的分类:1) 内部排序:指将
- 前言请看下面几个问题Spring为什么不推荐使用@Autowired 注解?为什么推荐使用@Resource 代替&nb
- 本文实例为大家分享了convinientbanner顶部广告轮播控件的具体代码,供大家参考,具体内容如下gradle中添加compile &
- Android Dialog 动画实例详解动画描述: 动画与底部菜单一样出现和消失制作过程:1. 创建两个动画文件window_in.xml
- 前言本节将介绍如何设置和使用MongoDB 驱动程序,通过 java实现与MongoDB服务端的通信功能,用户可以在此基础上进行各种Java
- 目录闲言碎语:背景Actuator介绍Rest方法来查看Actuatorpom.xml引入Actuator依赖配置application.y
- 前言最近需求中,需要实现 卫星菜单的需求,最终通过自定义View和动画属性来实现,具体功能如下:1.自定义Viewimport androi
- 在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理
- 本文实例为大家分享了java实现打砖块小游戏的具体代码,供大家参考,具体内容如下源码共包含两个文件文件1:play_zhuankuai.ja
- 这篇文章主要介绍了Java TreeSet类的简单理解和使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 本文实例讲述了C#读取csv格式文件的方法。分享给大家供大家参考。具体实现方法如下:一、CSV文件规则 1 开头是不留空,以行为单
- package com.test; import java.io.FileNotFoundException;&nbs
- 首先了解java构造函数怎么写java构造方法必须满足以下语法规则:(1) 方法名必须与类名相同。(2)不要声明返回类型。(3)不能被sta
- CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。