目录
一、实例
1.源码
2.生成效果
二、相关知识点
1.Thread类
(1)Thread.Sleep()方法
(2)Thread(ThreadStart)
(3)IsBackground
(4)Invoke( )
2.CreateGraphics()
3.DateTime.Now
4.(MethodInvoker)delegate ()
使用DateTime结构的Now静态属性可以轻松地获取当前系统时间。
DateTime结构的Now静态属性只是得到一个系统时间对象,该时间对象不会随着系统时间的变化而变化,如果要动态显示系统时间,可以使用计时器间隔地获取系统时间对象并显示。
可以适当地使用线程替代Timer控件。在窗体应用程序开发过程中,应当尽量避免使用窗体线程做高强度的运算或IO操作,如果窗体线程参与了过多的运算,会导致用户的操作不能及时分配到资源,用户界面会出现卡或无响应情况。
//使用DateTime的Now静态属性动态获取系统时间
namespace _053
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Load += Form1_Load;
}
private void Form1_Load(object? sender, EventArgs e)
{
SuspendLayout();
//
// Form1
//
AutoScaleDimensions = new SizeF(7F, 17F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(394, 41);
Name = "Form1";
StartPosition = FormStartPosition.CenterScreen;
Text = "动态获取系统时间";
ResumeLayout(false);
Thread thread = new(//创建线程
() => //使用lambda表达式
{
while (true) //无限循环
{
Invoke( //操作窗体线程
(MethodInvoker)delegate ()//使用匿名方法
{
Refresh();//刷新窗体
Graphics graphics = CreateGraphics(); //创建绘图对象
graphics.DrawString("系统时间:" + //在窗体中绘出系统时间
DateTime.Now.ToString("yyyy年MM月dd日 HH时mm分ss秒"),
new Font("Times New Roman", 14),
Brushes.Blue,
new Point(10, 10));
});
Thread.Sleep(1000);//线程挂起1秒钟
}
})
{
IsBackground = true //将线程设置为后台线程
};
thread.Start(); //线程开始执行
}
}
}
创建和控制线程,设置其优先级并获取其状态。
将当前线程挂起指定的时间。
Sleep(Int32) | 将当前线程挂起指定的毫秒数。 |
Sleep(TimeSpan) | 将当前线程挂起指定的时间。 |
将当前线程挂起指定的毫秒数。
public static void Sleep (int millisecondsTimeout);
参数
millisecondsTimeout Int32
挂起线程的毫秒数。 如果 millisecondsTimeout 参数的值为零,则该线程会将其时间片的剩余部分让给任何已经准备好运行的、具有同等优先级的线程。 如果没有其他已经准备好运行的、具有同等优先级的线程,则不会挂起当前线程的执行。
例外
ArgumentOutOfRangeException
超时值为负且不等于 Infinite。
// Sleep(Int32)
// 使用 Sleep 方法来阻止应用程序的main线程。
namespace ConsoleApp12
{
class Example
{
static void Main()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Sleep for 2 seconds.");
Thread.Sleep(2000);
}
Console.WriteLine("Main thread exits.");
}
}
}
/* 运行结果:
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Main thread exits.
*/
public static void Sleep (TimeSpan timeout);
参数
timeout TimeSpan
挂起线程的时间量。 如果 timeout 参数的值为 Zero,则该线程会将其时间片的剩余部分让给任何已经准备好运行的、具有同等优先级的线程。 如果没有其他已经准备好运行的、具有同等优先级的线程,则不会挂起当前线程的执行。
例外
ArgumentOutOfRangeException
的 timeout 值为负,不等于 Infinite 以毫秒为单位,或大于 Int32.MaxValue 毫秒。
// Sleep(TimeSpan)
// 使用 Sleep(TimeSpan) 方法重载来阻止应用程序的main线程五次,每次两秒。
namespace ConsoleApp13
{
class Example
{
static void Main()
{
TimeSpan interval = new(0, 0, 2);
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Sleep for 2 seconds.");
Thread.Sleep(interval);
}
Console.WriteLine("Main thread exits.");
}
}
}
/* 运行结果:
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Sleep for 2 seconds.
Main thread exits.
*/
初始化 Thread 类的新实例。
public Thread (System.Threading.ThreadStart start);
参数
start ThreadStart
表示开始执行此线程时要调用的方法的 ThreadStart 委托。
例外
ArgumentNullException
start 参数为 null。
// Thread(ThreadStart)
// 创建并执行静态方法的线程
namespace ConsoleApp10
{
class Test
{
static void Main()
{
Work.DoWork();
Thread newthread = new(Work.DoWork); //创建线程=把要处理的方法放进这个线程
Thread newThread = new(new ThreadStart(Work.DoWork)); //等效语句
newthread.Start();
newThread.Start();
}
}
class Work
{
public static void DoWork()
{
Console.WriteLine("Thread newThread=new()和 newThread.Start()总是成对出现的,");
Console.WriteLine("前者负责创建一个新线程,后者负责执行这个线程");
}
}
}
// 运行结果:
/*
Thread newThread=new()和 newThread.Start()总是成对出现的,
前者负责创建一个新线程,后者负责执行这个线程
Thread newThread=new()和 newThread.Start()总是成对出现的,
前者负责创建一个新线程,后者负责执行这个线程
Thread newThread=new()和 newThread.Start()总是成对出现的,
前者负责创建一个新线程,后者负责执行这个线程
*/
// 创建执行实例方法的线程
namespace ConsoleApp11
{
class Test
{
static void Main()
{
Work threadWork = new(); //创建实例方法
Thread newthread = new(Work.DoWork);
Thread newThread = new(new ThreadStart(Work.DoWork));
newthread.Start();
newThread.Start();
}
}
class Work
{
public static void DoWork()
{
Console.WriteLine("Thread newThread=new()和 newThread.Start()总是成对出现的,");
Console.WriteLine("前者负责创建一个新线程,后者负责执行这个线程");
}
}
}
//运行结果:
/*
Thread newThread=new()和 newThread.Start()总是成对出现的,
前者负责创建一个新线程,后者负责执行这个线程
Thread newThread=new()和 newThread.Start()总是成对出现的,
前者负责创建一个新线程,后者负责执行这个线程
*/
获取或设置一个值,该值指示某个线程是否为后台线程。
public bool IsBackground { get; set; }
属性值
Boolean
如果此线程为或将成为后台线程,则为 true;否则为 false。
例外
ThreadStateException
线程终止。
// Thread.IsBackground 属性
// 创建前台线程和后台线程,对前台线程和后台线程的行为进行对比。
// 前台线程使进程保持运行,直到完成其 for 循环并终止。
// 由于前台线程已完成执行,因此后台线程将终止进程。
namespace ConsoleApp15
{
class Example
{
static void Main()
{
BackgroundTest shortTest = new(5);
Thread foregroundThread =
new(new ThreadStart(shortTest.RunLoop));
BackgroundTest longTest = new(50);
Thread backgroundThread =
new(new ThreadStart(longTest.RunLoop))
{
IsBackground = true
};
foregroundThread.Start();
backgroundThread.Start();
}
}
class BackgroundTest(int maxIterations)
{
readonly int maxIterations = maxIterations;
public void RunLoop()
{
for (int i = 0; i < maxIterations; i++)
{
Console.WriteLine("{0} count: {1}",
Thread.CurrentThread.IsBackground ?
"Background Thread" : "Foreground Thread", i);
Thread.Sleep(250);
}
Console.WriteLine("{0} finished counting.",
Thread.CurrentThread.IsBackground ?
"Background Thread" : "Foreground Thread");
}
}
}
// 运行结果:
/*
Foreground Thread count: 0
Background Thread count: 0
Background Thread count: 1
Foreground Thread count: 1
Background Thread count: 2
Foreground Thread count: 2
Background Thread count: 3
Foreground Thread count: 3
Background Thread count: 4
Foreground Thread count: 4
Background Thread count: 5
Foreground Thread finished counting.
*/
详见本文作者发表的其他文章,C#用Parallel.Invoke 方法尽可能并行执行提供的每个操作-CSDN博客 https://wenchm.blog.csdn.net/article/details/135697802
将 TimeSpan 结构的新实例初始化为指定的小时数、分钟数和秒数。
public TimeSpan (int hours, int minutes, int seconds);
参数
hours Int32
小时数。
minutes Int32
分钟数。
seconds Int32
秒数。
例外
ArgumentOutOfRangeException
参数指定小于 TimeSpanTimeSpan.MinValue 或大于 TimeSpan.MaxValue 的值。
注解
将指定的 hours、 minutes和 seconds 转换为时钟周期,该值初始化此实例。
// Example of the TimeSpan( int, int, int ) constructor.
// 创建多个 TimeSpan 对象,该重载将 初始化 TimeSpan 为指定的小时数、分钟数和秒数。
namespace ConsoleApp14
{
class TimeSpanCtorIIIDemo
{
static void CreateTimeSpan(int hours, int minutes,int seconds)
{
TimeSpan elapsedTime = new(hours, minutes, seconds);
string ctor = string.Format("TimeSpan( {0}, {1}, {2} )",hours, minutes, seconds);
Console.WriteLine("{0,-37}{1,16}",ctor, elapsedTime.ToString());//输出格式
}
static void Main()
{
Console.WriteLine(
"This example of the TimeSpan( int, int, int ) " +
"\nconstructor generates the following output.\n");
Console.WriteLine("{0,-37}{1,16}", "Constructor", "Value"); //{0,-37}代表左对齐长度不足时空格抵
Console.WriteLine("{0,-37}{1,16}", "-----------", "-----"); //{1,16}代表右对齐,长度不足时空格抵
CreateTimeSpan(10, 20, 30);
CreateTimeSpan(-10, 20, 30);
CreateTimeSpan(0, 0, 37230);
CreateTimeSpan(1000, 2000, 3000);
CreateTimeSpan(1000, -2000, -3000);
CreateTimeSpan(999999, 999999, 999999);
}
}
}
/*
This example of the TimeSpan( int, int, int )
constructor generates the following output.
Constructor Value
----------- -----
TimeSpan( 10, 20, 30 ) 10:20:30
TimeSpan( -10, 20, 30 ) -09:39:30
TimeSpan( 0, 0, 37230 ) 10:20:30
TimeSpan( 1000, 2000, 3000 ) 43.02:10:00
TimeSpan( 1000, -2000, -3000 ) 40.05:50:00
TimeSpan( 999999, 999999, 999999 ) 42372.15:25:39
*/