一、进程Process



//获得当前程序中所有正在运行的进程
Process[] processes = Process.GetProcesses();
foreach (var item in processes)
{
//不试的不是爷们
//item.Kill();
Console.WriteLine(item);
}

//通过进程打开应用程序
Process.Start("calc");
Process.Start("mspaint");
Process.Start("notepad");
Process.Start("iexplore", "http://www.baidu.com");

//通过进程打开指定的文件
ProcessStartInfo psi = new ProcessStartInfo(@"C:\Users\liwen\Desktop\微信图片_20210104225821.png");
Process process = new Process() { StartInfo = psi };
process.Start();


 

二、线程Thread 

1、ThreadStart是一个无参的、返回值为void的委托。委托定义如下:public delegate void ThreadStart()

通过Lambda表达式创建线程



Thread thread = new Thread(() => { Console.WriteLine("我是通过Lambda表达式创建的委托线程"); });
thread.Start();


2、ParameterizedThreadStart是一个有参的、返回值为void的委托,定义如下:public delegate void ParameterizedThreadStart(Object obj)



Thread thread = new Thread((e)=> { Console.WriteLine(e); });
thread.Start("这是一个有参数的委托");


3、线程的属性与方法



//获取正在运行的线程
Thread thread = Thread.CurrentThread;
//设置线程的名字
thread.Name = "主线程";
//获取当前线程的唯一标识符
int id = thread.ManagedThreadId;
//获取当前线程的状态
ThreadState state = thread.ThreadState;
//获取当前线程的优先级
ThreadPriority priority = thread.Priority;
string strMsg = string.Format("Thread ID:{0}\n" + "Thread Name:{1}\n" +
"Thread State:{2}\n" + "Thread Priority:{3}\n", id, thread.Name,
state, priority);

Console.WriteLine(strMsg);


4、前台线程和后台线程-------前台线程:只有所有的前台线程都结束,应用程序才能结束。默认情况下创建的线程 都是前台线程

后台线程:只要所有的前台线程结束,后台线程自动结束。通过Thread.IsBackground设置后台线程。必须在调用Start方法之前设置线程的类型,否则一旦线程运行,将无法改变其类型。

 



static void Main(string[] args)
{
//演示前台、后台线程
BackGroundTest background = new BackGroundTest(10);
//创建前台线程
Thread fThread = new Thread(new ThreadStart(background.RunLoop));
//给线程命名
fThread.Name = "前台线程";


BackGroundTest background1 = new BackGroundTest(20);
//创建后台线程
Thread bThread = new Thread(new ThreadStart(background1.RunLoop));
bThread.Name = "后台线程";
//设置为后台线程
bThread.IsBackground = true;

//启动线程
fThread.Start();
bThread.Start();
}
class BackGroundTest
{
private int Count;
public BackGroundTest(int count)
{
this.Count = count;
}
public void RunLoop()
{
//获取当前线程的名称
string threadName = Thread.CurrentThread.Name;
for (int i = 0; i < Count; i++)
{
Console.WriteLine("{0}计数:{1}", threadName, i.ToString());
//线程休眠500毫秒
Thread.Sleep(1000);
}
Console.WriteLine("{0}完成计数", threadName);

}
}


运行结果:前台线程执行完,后台线程未执行完,程序自动结束。把bThread.IsBackground = true注释掉,运行结果:主线程执行完毕后(Main函数),程序并未结束,而是要等所有的前台线程结束以后才会结束

后台线程一般用于处理不重要的事情,应用程序结束时,后台线程是否执行完成对整个应用程序没有影响。如果要执行的事情很重要,需要将线程设置为前台线程。

 

 

 5、线程同步-----所谓同步:是指在某一时刻只有一个线程可以访问变量。



static void Main(string[] args)
{
BookShop book = new BookShop();
//创建两个线程同时访问Sale方法
Thread t1 = new Thread(new ThreadStart(book.Sale));
Thread t2 = new Thread(new ThreadStart(book.Sale));
//启动线程
t1.Start();
t2.Start();
Console.ReadKey();
}
class BookShop
{
//剩余图书数量
public int num = 1;
public void Sale()
{
//使用lock关键字解决线程同步问题
lock (this)
{
int tmp = num;
if (tmp > 0)//判断是否有书,如果有就可以卖
{
Thread.Sleep(1000);
num -= 1;
Console.WriteLine("售出一本图书,还剩余{0}本", num);
}
else
{
Console.WriteLine("没有了");
}
}
}
}


6、跨线程访问-----在窗体的加载事件中,将C#内置控件(Control)类的CheckForIllegalCrossThreadCalls属性设置为false,屏蔽掉C#编译器对跨线程调用的检查。



private void Form1_Load(object sender, EventArgs e)
{
//取消跨线程的访问
Control.CheckForIllegalCrossThreadCalls = false;
}


使用回调机制-----C#的方法回调机制,也是建立在委托基础上的,下面给出它的典型实现过程



//定义回调
private delegate void setTextValueCallBack(int value);

public void ThreadCallBackT()
{
//实例化回调
var setCallBack = new setTextValueCallBack((e) => { Console.WriteLine(e); });
//创建一个线程去执行这个方法:创建的线程默认是前台线程
Thread thread = new Thread(new ThreadStart(()=>
{
for (int i = 0; i < 100; i++)
{
//使用回调
setCallBack.Invoke(i);
}
}));
//Start方法标记这个线程就绪了,可以随时被执行,具体什么时候执行这个线程,由CPU决定
//将线程设置为后台线程
thread.IsBackground = true;
thread.Start();
}


 

 

一个线程的封装案列



class ThreadHelper
{
public static void TestDemo()
{
ThreadHelper threadHelper = new ThreadHelper();
{
void threadStart() { Thread.Sleep(2000); Console.WriteLine("Thread第一个执行的委托方法"); };
Action action = () => { Console.WriteLine("第二个执行的委托方法"); };
threadHelper.ThreadWithCallBack(threadStart, action);
}


{
//定义一个返回值类型为int的无参数委托,在新线程中调用
Func<int> func = () => { Thread.Sleep(2000); return DateTime.Now.Day; };
//将func作为参数传入扩展方法执行,并用变量接收返回的委托类型
Func<int> funResult = threadHelper.ThreadWithReturn(func);
//执行委托接收返回值
int iResult = funResult.Invoke();
Console.WriteLine(iResult);
}
}
/// <summary>
/// 扩展封装Thread
/// </summary>
/// <param name="threadStart">开启新线程需要执行的任务</param>
/// <param name="actionCallback">任务执行后紧接着需要执行的任务</param>
private void ThreadWithCallBack(ThreadStart threadStart, Action actionCallback)
{
ThreadStart threadStart1 = new ThreadStart(() =>
{
threadStart.Invoke();
actionCallback.Invoke();
});
Thread thread = new Thread(threadStart1);
thread.Start();
}

/// <summary>
/// 扩展封装Thread,有返回值,需要获取结果的时候运行委托,卡界面
/// </summary>
/// <typeparam name="T">委托执行后的返回值</typeparam>
/// <param name="func">开启新线程需要执行的任务</param>
/// <returns></returns>
private Func<T> ThreadWithReturn<T>(Func<T> func)
{
//指定泛型默认值
T t = default(T);

ThreadStart threadStart = new ThreadStart(() => { t = func.Invoke(); });
Thread thread = new Thread(threadStart);
thread.Start();

return new Func<T>(() => { thread.Join(); return t; });
}
}