版权声明:未经允许,不可转载。 https://blog.csdn.net/zhengxu25689/article/details/82892498
这篇文章之所以称之为实时线程监控类的改进,是因为在先前写过一篇关于《C# 一个线程实时监控类 》,是对这个类的一个改进。
PS:这里说明下,关于《C# 一个线程实时监控类》为何要自己去实现,而不是直接使用C#本身的类库Task,可以参考我的另一篇关于《C#中如果正确使用线程Task类和Thread类》,文章中说明了问题的原因。
这篇文章即然是为了实现实时线程监控类,所以在实现类是将Thread类进行封装,以便于使用上的尽可能方便和简洁(达到Task的使用效果)以及保证线程本身的实时性强(不受硬件CPU问题)。
在实现过程中通过两个类来完成:
-
AutomateThread:对线程类Thread的封装。
- StartNew:新建并立即启动一个后台线程, 不等待线程完成。
/// <summary> /// Starts the new thread. /// </summary> /// <param name="start">The start.</param> /// <param name="priority">The priority.</param> /// <returns>Thread.</returns> public static Thread StartNew(ThreadStart start, ThreadPriority priority = ThreadPriority.Normal) { Thread t = new Thread(start); t.IsBackground = true; t.Priority = priority; t.Start(); return t; }
- TasksExecuteAsyn:新建并立即启动多个后台线程, 等待所有线程完成。
/// <summary> /// Taskses the execute asyn. /// </summary> /// <param name="starts">The starts.</param> public static void TasksExecuteAsyn(params ThreadStart[] starts) { int count=starts.Length; ManualResetTask task = new ManualResetTask(count); for (int i = 0; i < starts.Length; i++) { ThreadStart run = starts[i]; StartNew(new ThreadStart(() => { run(); task.NotifiyThreadCompleted(); })); } task.Wait(); }
未改进代码如下:
/// <summary> /// Taskses the execute asyn. /// </summary> /// <param name="starts">The starts.</param> public static void TasksExecuteAsyn(params ThreadStart[] starts) { Thread[] threads = new Thread[starts.Length]; for (int i = 0; i < starts.Length; i++) { threads[i] = StartNew(starts[i]); } WaitAll(threads); } /// <summary> /// Waits all. /// </summary> /// <param name="threads">The threads.</param> public static void WaitAll(params Thread[] threads) { foreach (Thread t in threads) { while (t != null && t.IsAlive) { Thread.Sleep(1); } } }
- Monitor:新建并立即启动一个后台线程,并监控线程是否在指定的时间内完成结束。
/// <summary>
/// Monitors the specified period.
/// </summary>
/// <param name="period">The period.</param>
/// <param name="start">The start.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public static bool Monitor(int period, ThreadStart start)
{
ManualResetTask task = new ManualResetTask(1);
StartNew(new ThreadStart(() =>
{
start();
task.NotifiyThreadCompleted();
}));
return !task.Wait(period);
}
未改进前代码如下:
/// <summary>
/// Monitors the specified period.
/// </summary>
/// <param name="period">The period.</param>
/// <param name="start">The start.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public static bool Monitor(int period, ThreadStart start)
{
Tickwatch sw = Tickwatch.StartNew();
Thread t = AutomateThread.StartNew(start);
while (sw.ElapsedMilliseconds < period)
{
if (!t.IsAlive)
{
return false;
}
AutomateThread.Sleep(1);
}
return true;
}
-
ManualResetTask:监控多个AutomateThread线程等待执行完成。
应该可以注意到,ManualResetTask类的实现主要是改进AutomateThread等待线程执行完成的实现代码作了改进。
未改进版本: 采用Thread.Sleep(),循环等待所有启动的线程,直到所有线程完成为止。采用Thread.Sleep()方法是根据CPUxg程时间片轮循的机制进行判断,时间较不准确。目前在双核CPU情况下,Thread.Sleep(1)大约时间精度为15ms。
改进版本:使用ManualResetTask,主要采用ManualResetEvent,通过事件通知来完成,时间的精度比Thread.Sleep(1)高,且较为稳定。关于ManualResetEvent,可以自行查看MSDN资料。
AutomateThread实现代码如下:
// ***********************************************************************
// Assembly : Common.Class
// Author : maojun.zheng
// Created : 2017-05-25
//
// Last Modified By : maojun.zheng
// Last Modified On : 2018-03-06
// ***********************************************************************
// <copyright file="AutomateThread.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System.Collections.Generic;
using System.Threading;
/// <summary>
/// The Common namespace.
/// </summary>
namespace Common.Class
{
/// <summary>
/// Class AutomateThread.
/// </summary>
public class AutomateThread
{
/// <summary>
/// Starts the new.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="priority">The priority.</param>
/// <returns>Thread.</returns>
public static Thread StartNew(ThreadStart start, ThreadPriority priority = ThreadPriority.Normal)
{
Thread t = new Thread(start);
t.IsBackground = true; //这里简单说明下:设置线程为后台线程,不清楚的可自行查阅下
t.Priority = priority;
t.Start();
return t;
}
/// <summary>
/// Taskses the execute asyn.
/// </summary>
/// <param name="starts">The starts.</param>
public static void TasksExecuteAsyn(params ThreadStart[] starts)
{
int count=starts.Length;
ManualResetTask task = new ManualResetTask(count);
for (int i = 0; i < starts.Length; i++)
{
ThreadStart run = starts[i];
StartNew(new ThreadStart(() =>
{
run();
task.NotifiyThreadCompleted();
}));
}
task.Wait();
}
/// <summary>
/// Monitors the specified period.
/// </summary>
/// <param name="period">The period.</param>
/// <param name="start">The start.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public static bool Monitor(int period, ThreadStart start)
{
ManualResetTask task = new ManualResetTask(1);
StartNew(new ThreadStart(() =>
{
start();
task.NotifiyThreadCompleted();
}));
return !task.Wait(period);
}
}
}
ManualResetTask代码实现如下:
// ***********************************************************************
// Assembly : Common.Class
// Author : maojun.zheng
// Created : 2018-09-28
//
// Last Modified By : maojun.zheng
// Last Modified On : 2018-09-19
// ***********************************************************************
// <copyright file="ManualResetTask.cs" company="">
// Copyright (c) . All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// The Class namespace.
/// </summary>
namespace Common.Class
{
/// <summary>
/// Class ManualResetTask.
/// </summary>
public class ManualResetTask
{
/// <summary>
/// The thread count
/// </summary>
private readonly int threadCount;
/// <summary>
/// The count
/// </summary>
private int count ;
/// <summary>
/// The root
/// </summary>
private object root;
/// <summary>
/// Initializes a new instance of the <see cref="ManualResetTask"/> class.
/// </summary>
/// <param name="threadCount">The thread count.</param>
public ManualResetTask(int threadCount)
{
this.threadCount = threadCount;
this.count = 0;
this.resetEvent = new ManualResetEvent(false);
this.root = new object();
}
/// <summary>
/// The reset event
/// </summary>
private ManualResetEvent resetEvent;
/// <summary>
/// Notifiys the thread completed.
/// </summary>
public void NotifiyThreadCompleted()
{
lock(this.root)
{
this.count++;
if (count >= this.threadCount)
{
this.resetEvent.Set();
}
}
}
/// <summary>
/// Waits this instance.
/// </summary>
public void Wait()
{
this.resetEvent.WaitOne();
}
/// <summary>
/// Waits the specified milliseconds timeout.
/// </summary>
/// <param name="millisecondsTimeout">The milliseconds timeout.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public bool Wait(int millisecondsTimeout)
{
return this.resetEvent.WaitOne(millisecondsTimeout);
}
}
}