创建线程

using System;
using System.Threading;
using System.Threading.Tasks; namespace threadDemo
{ class Program
{
static void PrintNumbers()
{
Console.WriteLine("Starting to print numbers...");
for(int i = 0; i < 10; i++) {
{
Console.WriteLine(i);
} }
}
public static void Main(string[] args)
{
var t = new Thread(PrintNumbers);
t.Start();
PrintNumbers(); }
}
}

output:

Starting to print numbers...
Starting to print numbers...
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9

从结果看,PrintNumbers方法同时运行在主线程和另一个线程中。

暂停线程

using System;
using System.Threading;
using System.Threading.Tasks; namespace threadDemo
{ class Program
{
static void PrintNumbers()
{
Console.WriteLine("Starting to print numbers...");
for(int i = 0; i < 10; i++) {
{
Console.WriteLine(i);
} }
}
static void PrintNumbersWithDelay()
{
Console.WriteLine("Starting to print numbers with delay...");
for(int i = 10; i < 20; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
public static void Main(string[] args)
{
var t = new Thread(PrintNumbersWithDelay);
t.Start();
PrintNumbers(); }
}
}

ouput

Starting to print numbers with delay...
Starting to print numbers...
0
1
2
3
4
5
6
7
8
9
10
11

最终如下:

Starting to print numbers with delay...
Starting to print numbers...
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

程序运行时,会创建一个线程,该线程会立即执行PrintNumbersWithDelay方法中的代码,然后立即执行PrintNumber方法,而PrintNumbersWithDelay中的Sleep方法,会导致线程执行该代码时,在打印任何数字之前会等待指定的时间(2s),当线程处于休眠状态时,它会占用尽可能少的CPU时间,然后我们就发现程序先执行了PrintNumber方法。

线程等待

using System;
using System.Threading;
using System.Threading.Tasks; namespace threadDemo
{ class Program
{
static void PrintNumbers()
{
Console.WriteLine("Starting to print numbers...");
for(int i = 0; i < 10; i++) {
{
Console.WriteLine(i);
} }
}
static void PrintNumbersWithDelay()
{
Console.WriteLine("Starting to print numbers with delay...");
for(int i = 10; i < 20; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
public static void Main(string[] args)
{
var t = new Thread(PrintNumbersWithDelay);
t.Start();
t.Join();
PrintNumbers(); }
}
}

output:

Starting to print numbers with delay...
10
11
12
13
14
15

最终:

Starting to print numbers with delay...
10
11
12
13
14
15
16
17
18
19
Starting to print numbers...
0
1
2
3
4
5
6
7
8
9

在主程序调用了t.Join方法,该方法允许我们等待直到t线程完成。借助这个技术,可以让一个线程等待另一个线程结束后再继续执行。

终止线程

线程的Abort方法只能用在Net Framework中,而不能 用在.Net Core中。

using System;
using System.Threading;
using System.Threading.Tasks; namespace threadDemo
{ class Program
{
static void PrintNumbers()
{
Console.WriteLine("Starting to print numbers...");
for (int i = 0; i < 10; i++)
{
{
Console.WriteLine(i);
}
}
}
static void PrintNumbersWithDelay()
{
Console.WriteLine("Starting to print numbers with delay...");
for (int i = 10; i < 20; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
public static void Main(string[] args)
{
var t = new Thread(PrintNumbersWithDelay);
t.Start();
Thread.Sleep(TimeSpan.FromSeconds(6));
t.Abort();
Console.WriteLine("A thread has been aborted");
PrintNumbers(); }
}
}

output:

Starting to print numbers with delay...
10
11
A thread has been aborted
Starting to print numbers...
0
1
2
3
4
5
6
7
8
9

值得注意的 是:调用t.Abort方法,给线程注入了ThreadAbortException方法,导致线程被终结,这非常危险,因为该异常可以在任何时刻发生并可能彻底摧毁应用程序,另外,该技术也不一定能终止线程,目标线程可以通过处理该异常,并调用Thread.ResetAbort方法来拒绝被终止。可以使用CancellationToken方法来取消线程的执行

检测线程状态

获取线程是否已经启动,或是否处于阻塞状态等相应信息是非常有用的,由于线程是独立运行的,所以其 状态在任何时候都可以被改变。

using System;
using System.Threading;
using System.Threading.Tasks; namespace threadDemo
{
class Program
{
static void DoNothing()
{
Console.WriteLine("Start to do nothing");
Thread.Sleep(TimeSpan.FromSeconds(2));
}
static void PrintNumbersWithStatus()
{
Console.WriteLine("Starting PrintNumbersWithStatus....");
Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
for(int i = 20; i < 30; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
static void PrintNumbers()
{
Console.WriteLine("Starting to print numbers...");
for (int i = 0; i < 10; i++)
{
{
Console.WriteLine(i);
}
}
}
static void PrintNumbersWithDelay()
{
Console.WriteLine("Starting to print numbers with delay...");
for (int i = 10; i < 20; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(i);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Starting program....");
Thread t = new Thread(PrintNumbersWithStatus);
Thread t2 = new Thread(DoNothing);
Console.WriteLine(t.ThreadState.ToString());
t2.Start();
t.Start();
for(int i = 0; i < 30; i++)
{
Console.WriteLine("t status:"+t.ThreadState.ToString());
Console.WriteLine("t2 status:"+ t2.ThreadState.ToString());
}
Thread.Sleep(TimeSpan.FromSeconds(6));
t.Abort();
Console.WriteLine("A thread has been aborted");
Console.WriteLine(t.ThreadState.ToString());
Console.WriteLine(t2.ThreadState.ToString()); }
}
}

output:

Starting program....
Unstarted
Start to do nothing
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
t2 status:WaitSleepJoin
t status:Running
Starting PrintNumbersWithStatus....
Running
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
t status:WaitSleepJoin
t2 status:WaitSleepJoin
20
21
A thread has been aborted
Aborted
Stopped

值得注意的是,始终可以通过Thread.CurrentThread静态属性获取当前Thread对象。

线程优先级

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
class ThreadSample
{
private bool _isStopped = false;
public void Stop()
{
_isStopped = true;
}
public void CountNumbers()
{
long counter = 0;
while (!_isStopped)
counter++; Console.WriteLine($"{Thread.CurrentThread.Name} with" + $"{Thread.CurrentThread.Priority,11} priority" +
$"has a count ={counter,13:N0}"
) ;
}
}
class Program
{
static void RunThreads()
{
var sample = new ThreadSample();
var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne";
var threadTwo = new Thread(sample.CountNumbers);
threadTwo.Name = "ThreadTwo"; threadOne.Priority = ThreadPriority.Highest;
threadTwo.Priority = ThreadPriority.Lowest; threadOne.Start();
threadTwo.Start(); Thread.Sleep(TimeSpan.FromSeconds(2));
sample.Stop();
} public static void Main(string[] args)
{
Console.WriteLine($"Current thread priority:{Thread.CurrentThread.Priority}");
Console.WriteLine($"Running on all cores available");
RunThreads();
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("Running on a single core");
//该项设置,让操作系统将所有线程运行在单个CPU核心上。
Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);//C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。
RunThreads(); }
}
}

output

Current thread priority:Normal
Running on all cores available
ThreadOne with Highest priorityhas a count =1,146,211,615
ThreadTwo with Lowest priorityhas a count =1,141,020,465
Running on a single core
ThreadOne with Highest priorityhas a count =10,764,547,004
ThreadTwo with Lowest priorityhas a count = 40,141,151

前后台线程

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
class ThreadSample
{
private readonly int _iterations;
public ThreadSample(int iterations)
{
_iterations = iterations;
}
public void CountNumbers()
{
for(int i = 0; i < _iterations; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine($"{Thread.CurrentThread.Name} prints{i}");
}
}
}
class Program
{ public static void Main(string[] args)
{
var sampleForeground = new ThreadSample(10);
var sampleBackground = new ThreadSample(20);
var threadOne = new Thread(sampleForeground.CountNumbers);
var threadTwo = new Thread(sampleBackground.CountNumbers); threadOne.Name = "Foreground";
threadTwo.Name = "Background";
threadTwo.IsBackground = true; threadOne.Start();
threadTwo.Start(); }
}
}

output:

Background prints0
Foreground prints0
Foreground prints1
Background prints1
Background prints2
Foreground prints2
Foreground prints3
Background prints3
Foreground prints4
Background prints4
Background prints5
Foreground prints5
Foreground prints6
Background prints6
Background prints7
Foreground prints7
Background prints8
Foreground prints8
Foreground prints9
Background prints9

默认情况下,显式创建的线程是前台线程,通过手动设置的IsBackground属性为true来创建一个后台线程.

前台线程与后台线程的主要区别就是:进程会等待所有的前台线程完成后再结束工作,但是如果只剩下后台线程,则不等待,直接结束工作。

        public static void Main(string[] args)
{
var sampleForeground = new ThreadSample(10);
var sampleBackground = new ThreadSample(20);
var threadOne = new Thread(sampleForeground.CountNumbers);
var threadTwo = new Thread(sampleBackground.CountNumbers); threadOne.Name = "Foreground";
threadTwo.Name = "Background";
//threadTwo.IsBackground = true; threadOne.Start();
threadTwo.Start(); }

将设置为后台线程的代码注释掉,结果如下:

Background prints0
Foreground prints0
Foreground prints1
Background prints1
Foreground prints2
Background prints2
Foreground prints3
Background prints3
Foreground prints4
Background prints4
Background prints5
Foreground prints5
Foreground prints6
Background prints6
Foreground prints7
Background prints7
Background prints8
Foreground prints8
Foreground prints9
Background prints9
Background prints10
Background prints11
Background prints12
Background prints13
Background prints14
Background prints15
Background prints16
Background prints17
Background prints18
Background prints19

一个重要的注意事项是:如果程序定义了一个不会完成的前台线程,主程序并不会正常结束。

向线程传递参数

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
class ThreadSample
{
private readonly int _iterations;
public ThreadSample(int iterations)
{
_iterations = iterations;
}
public void CountNumbers()
{
for(int i = 0; i < _iterations; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine($"{Thread.CurrentThread.Name} prints{i}");
}
}
}
class Program
{ static void Count(object iterations)
{
CountNumbers((int)iterations);
} static void CountNumbers(int iterations)
{
for(int i = 1; i <= iterations; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine($"{Thread.CurrentThread.Name} Prints {i}");
}
} public static void Main(string[] args)
{
//方法一 :通过类的实例方法传递参数
var sample = new ThreadSample(10);
var threadOne = new Thread(sample.CountNumbers);
threadOne.Name = "ThreadOne";
threadOne.Start();
threadOne.Join();
Console.WriteLine("Method one".PadLeft(50, '-'));
//方法二:通过接受一个参数的函数
var threadTwo = new Thread(Count);
threadTwo.Name = "ThreadTwo";
threadTwo.Start(8);//Start方法中赋值
threadTwo.Join();
Console.WriteLine("Method two".PadLeft(50, '-'));
//方法三:通过匿名函数lambda
var threadThree = new Thread(() => CountNumbers(12));
threadThree.Name = "ThreadThree";
threadThree.Start();
threadThree.Join();
Console.WriteLine("Mehtod three".PadLeft(50, '-'));
//方法四
int i = 10;
var threadFour = new Thread(() => CountNumbers(i));//i在后面变为20,故该线程中的i也变更为20
i = 20;
var threadFive = new Thread(() => CountNumbers(i));
threadFour.Name = "ThreadFour";
threadFive.Name = "ThreadFive";
threadFive.Start();
threadFour.Start();
}
}
}

output:

ThreadOne prints0
ThreadOne prints1
ThreadOne prints2
ThreadOne prints3
ThreadOne prints4
ThreadOne prints5
ThreadOne prints6
ThreadOne prints7
ThreadOne prints8
ThreadOne prints9
----------------------------------------Method one
ThreadTwo Prints 1
ThreadTwo Prints 2
ThreadTwo Prints 3
ThreadTwo Prints 4
ThreadTwo Prints 5
ThreadTwo Prints 6
ThreadTwo Prints 7
ThreadTwo Prints 8
----------------------------------------Method two
ThreadThree Prints 1
ThreadThree Prints 2
ThreadThree Prints 3
ThreadThree Prints 4
ThreadThree Prints 5
ThreadThree Prints 6
ThreadThree Prints 7
ThreadThree Prints 8
ThreadThree Prints 9
ThreadThree Prints 10
ThreadThree Prints 11
ThreadThree Prints 12
--------------------------------------Mehtod three
ThreadFour Prints 1
ThreadFive Prints 1
ThreadFive Prints 2
ThreadFour Prints 2
ThreadFour Prints 3
ThreadFive Prints 3
ThreadFive Prints 4
ThreadFour Prints 4
ThreadFive Prints 5
ThreadFour Prints 5
ThreadFive Prints 6
ThreadFour Prints 6
ThreadFour Prints 7
ThreadFive Prints 7
ThreadFive Prints 8
ThreadFour Prints 8
ThreadFive Prints 9
ThreadFour Prints 9
ThreadFive Prints 10
ThreadFour Prints 10
ThreadFour Prints 11
ThreadFive Prints 11
ThreadFive Prints 12
ThreadFour Prints 12
ThreadFour Prints 13
ThreadFive Prints 13
ThreadFour Prints 14
ThreadFive Prints 14
ThreadFour Prints 15
ThreadFive Prints 15
ThreadFour Prints 16
ThreadFive Prints 16
ThreadFour Prints 17
ThreadFive Prints 17
ThreadFive Prints 18
ThreadFour Prints 18
ThreadFour Prints 19
ThreadFive Prints 19
ThreadFive Prints 20
ThreadFour Prints 20

C#中的lock关键字

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
abstract class CounterBase
{
public abstract void Increment();
public abstract void Decrement();
}
class Counter : CounterBase
{
public int Count { get; set; }
public override void Decrement()
{
Count--;
} public override void Increment()
{
Count++;
}
}
class CounterWithLock : CounterBase
{
private readonly object _synRoot = new object();
public int Count { get; private set; }
public override void Decrement()
{
lock (_synRoot)
{
Count--;
}
} public override void Increment()
{
lock (_synRoot)
{
Count++;
}
}
}
class Program
{
static void TestCounter(CounterBase c)
{
for(int i = 0; i < 100000; i++)
{
c.Increment();
c.Decrement();
}
}
public static void Main(string[] args)
{
Console.WriteLine("Incorrect counter");
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c.Count}");
Console.WriteLine("-".PadLeft(50, '-'));
Console.WriteLine("Correct counter");
var c1 = new CounterWithLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t3 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c1.Count}");
}
}
}

output:

Incorrect counter
Total count:33
--------------------------------------------------
Correct counter
Total count:0

当多个线程共同享用进程中同一资源时,如果出现竞争条件,则需要保证有线程操作共用资源时,其他线程必须等待直到当前线程完成操作,可以用lock实现这种行为。如果锁定了一个对象,需要访问该对象的其他所有线程均处于阻塞状态,并等待直到对该对象解除锁定。

用Monitor类锁定资源

另一个常见的多线程错误是死锁。比如:如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁,因此因为争夺资源造成的一种僵局,当进程处于这种僵持状态,若无外力作用,它们都将无法再向前推进。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
class Program
{
static void LockTooMuch(object lock1,object lock2)
{
lock (lock1)
{
Thread.Sleep(1000);
lock (lock2) { }
}
}
public static void Main(string[] args)
{
var lock1 = new object();
var lock2 = new object();
new Thread(() => LockTooMuch(lock1, lock2)).Start();
lock (lock2)
{
Thread.Sleep(1000);
Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false" +
"after a specified timeout is elapsed"
);
if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5)))
{
Console.WriteLine("Acquired a protected resource succesully");
}
else
{
Console.WriteLine("Timeout acquiring a resource");
}
} new Thread(() => LockTooMuch(lock1, lock2)).Start();
Console.WriteLine("-".PadLeft(50, '-'));
lock (lock2)
{
Console.WriteLine("This will be a deadlock");
Thread.Sleep(1000);
lock (lock1)
{
Console.WriteLine("Acquired a protected resource successfully");
}
}
}
}
}

output:

Monitor.TryEnter allows not to get stuck, returning falseafter a specified timeout is elapsed
Timeout acquiring a resource
--------------------------------------------------
This will be a deadlock

通过Monitor.TryEnter方法,该方法接受一个超时参数,如果在我们能够获取被lock保护的资源之前,超时参数过期,则该方法会返回false.

处理异常

在线程中try/catch是非常重要的,因为不可能在线程代码外捕获异常。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace threadDemo
{
class Program
{
//not recommended
static void BadFaultyThread()
{
Console.WriteLine("Starting a faulty thread...");
Thread.Sleep(TimeSpan.FromSeconds(2));
throw new Exception("Boom!");
}
//recommended
static void FaultyThread()
{
try
{
Console.WriteLine("Starting a faultyy thread...");
Thread.Sleep(TimeSpan.FromSeconds(1));
throw new Exception("Boom!");
}
catch (Exception e)
{
Console.WriteLine($"Exception handled:{e.Message}");
}
}
public static void Main(string[] args)
{
var t = new Thread(FaultyThread);
t.Start();
t.Join(); ///捕捉不到异常!!!只能在线程内捕捉
try
{
t = new Thread(BadFaultyThread);
t.Start();
}
catch(Exception e)
{
Console.WriteLine($"We won't get here!");
} }
}
}

output

Starting a faultyy thread...
Exception handled:Boom!
Starting a faulty thread... 未经处理的异常: System.Exception: Boom!
在 threadDemo.Program.BadFaultyThread() 位置 E:\LearningCSharp\ThreadTestNetFramework\ThreadDemo\Program.cs:行号 14
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
请按任意键继续. . .

发送信号:

using System.Diagnostics;

var signal = new ManualResetEvent(false);
var t = new Thread(() =>
{
Console.WriteLine("watiging for signal....");
Console.WriteLine("");
Console.Write("输入");
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("n");
Console.ResetColor();
Console.Write("发送信号:");
signal.WaitOne();
signal.Dispose();
Console.WriteLine("Got signal");
});
t.Start(); var a = Console.ReadLine();
if (a == "n")
{
signal.Set();
}

C#之线程基础的更多相关文章

  1. Qt之线程基础

    何为线程 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据计算的时候,在相同的桌面上可能有一个播放器正在播放你最喜欢的歌曲.这是一个两个进程并行工作的例 ...

  2. Android多线程研究(1)——线程基础及源代码剖析

    从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部. 一.线程基础回想 package ...

  3. JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)

    实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...

  4. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  5. C#当中的多线程_线程基础

    前言 最近工作不是很忙,想把买了很久了的<C#多线程编程实战>看完,所以索性把每一章的重点记录一下,方便以后回忆. 第1章 线程基础 1.创建一个线程 using System; usin ...

  6. Qt 线程基础(Thread Basics的翻译,线程的五种使用情况)

    Qt 线程基础(QThread.QtConcurrent等) 转载自:http://blog.csdn.net/dbzhang800/article/details/6554104 昨晚看Qt的Man ...

  7. 线程基础(CLR via C#)

    1.线程基础  1.1.线程职责  线程的职责是对CPU进行虚拟化.Windows 为每个进程豆提供了该进程专用的线程(功能相当于一个CPU).应用程序的代码进入死循环,于那个代码关联的进程会&quo ...

  8. Linux 系统应用编程——线程基础

    传统多任务操作系统中一个可以独立调度的任务(或称之为顺序执行流)是一个进程.每个程序加载到内存后只可以唯一地对应创建一个顺序执行流,即传统意义的进程.每个进程的全部系统资源是私有的,如虚拟地址空间,文 ...

  9. python2 线程基础

    1,感谢菜鸟教程, 线程基础:导入,创建函数,创建线和运行 import thread import time # 为线程定义一个函数 def print_time(threadName, delay ...

  10. 《CLR via C#》读书笔记 之 线程基础

    第二十五章 线程基础 2014-06-28 25.1 Windows为什么要支持线程 25.2 线程开销 25.3 停止疯狂 25.6 CLR线程和Windows线程 25.7 使用专用线程执行异步的 ...

随机推荐

  1. Postman 接口测试工具详解

    一.引言 在软件开发和测试过程中,接口测试是至关重要的环节.Postman 作为一款功能强大的接口测试工具,为开发者和测试人员提供了便捷高效的测试解决方案. 二.Postman 简介 Postman ...

  2. Java - 高射炮打蚊子(第二弹)

    题记部分 01 || 面试题 001 || 什么是JVM JVM(Java虚拟机)是Java程序运行的环境,它是一个抽象的计算机,包括指令集.寄存器集.堆栈.垃圾回收等.JVM屏蔽了与具体操作系统平台 ...

  3. Ansible - [04] 关于sudo的一些配置

    sudo sudo,以超级管理员或其他人的身份执行命令 基本流程 管理员需要先授权(修改/etc/sudoers文件) 普通用户以sudo的形式执行命令 可以通过sudo -l查看授权情况 配置sud ...

  4. Featurewiz-Polars:一种强大且可扩展的特征选择解决方案,适用于XGBoost

    前言:"Featurewiz-Polars"是一个用于特征工程的 Python 库,结合了特征选择和特征生成的功能.它基于"Polars",这是一个高性能的 D ...

  5. DeepSeek满血版测试

    技术背景 很多厂商以次充好,用蒸馏版DeepSeek冒充满血版.本文提供一些收集的问题集,可以用于测试是否满血DeepSeek.经过实际测试,国内厂商中只有满血版DeepSeek可以全对.但是各厂商后 ...

  6. go ceph s3文件管理

    导入依赖 go get gopkg.in/amz.v1/aws go get gopkg.in/amz.v1/s3 创建用户 在初始化连接之前,我们需要创建一个用户得到accessKey和secret ...

  7. 关于Primavera P6版本选择上的一些看法

    从开始接触P6到目前也有近6年的时间,从最开始用的V7 (除P6.2.1)到现在用的18.8.0 ,除去一些小版本,中间自己跨越了8个不同版本    7.0,  (2013)    8.2       ...

  8. StringBuilder的介绍、构造方法及成员方法

    1.StringBuilder的介绍 1.StringBuilder是字符串缓冲区,可以认为是一种容器,能装任何类型的数据,但被装入的数据都会变为字符串 如图 无论是什么类型的数据,被装入字符串缓冲区 ...

  9. 搭建Trae+Vue3的AI开发环境

    从2024年2025年,不断的有各种AI工具会在自媒体中火起来,号称各种效率王炸,而在AI是否会替代打工人的话题中,程序员又首当其冲. 作为一个后端开发,这篇文章基于Trae工具,来创建和运行一个简单 ...

  10. C#+Appium+Nunit实现app自动化demo

    1.新建Nunit工程 打开Rider新建一个Nunit工程并使用NuGet安装对应库,步骤如下: 2.编写代码 代码如下: using System; using NUnit.Framework; ...