一、委託
//聲明委託
internal delegate int MyAddFunDel(int a,int b);
class Program
{
static void Main(string[] args)
{
MyAddFunDel funDel = new MyAddFunDel(AddStatic);
//多播
funDel += Add2;
Console.WriteLine(funDel(3,2));
Console.ReadKey();
}
static int AddStatic(int a, int b)
{
Console.WriteLine("AddStatic執行了\r\n");
return a + b;
}
static int Add2(int a, int b)
{
Console.WriteLine("Add2執行了\r\n");
return a++;
}
}
輸出結果:
#region 匿名函數
MyAddFunDel delFun = delegate(int i, int i1) { return i + i1; };
Console.WriteLine(delFun(3,2));
//lambda 其中 => goto,是lambda的一個標準
MyAddFunDel delLambda = (int i, int i1) => { return i + i1; };
lambda表達式的方法參數類型可以省略,類型由委託定義確定,即
MyAddFunDel delLambda = ( i, i1) => { return i + i1; };
只有一行代碼的時候還可以省略花括號,即
MyAddFunDel delLambda = ( i, i1) => return i + i1;
二、託管、非託管
三、擴展方法:三要素(靜態類、靜態方法、this)
FindAll方法的源代碼:
public List<T> FindAll(Predicate<T> match)
{
if (match == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
List<T> list = new List<T>();
for (int i = 0; i < this._size; i++)
{
if (match(this._items[i]))
{
list.Add(this._items[i]);
}
}
return list;
}
模擬FindAll的擴展方法(MyFindStrs<T>)
namespace可以改爲System.Collection.Generic,將擴展方法的命名空間和要擴展的類寫成一樣的
this後面緊跟的類型是擴展方法要加到的類型
方法名後面緊跟的泛型約束是最主要的
list.MyFindStrs<String> 其中<String>可以省略
namespace System.Collections.Generic //改namespace,使擴展方法的命名空間和要擴展的類所在命名空間一樣
{
class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>()
{
"1",
"2",
"3",
"4"
};
//MyFindStrs後面的<string>可以省略,因爲調用它的list集合的類型已經確定了(在這裏是string)
//自己模擬的方法
//var temp = list.MyFindStrs<string>(MyCal);
//普通寫法
//var temp = list.FindAll(MyCal);
//委託簡寫(lambda表達式)
var temp = list.FindAll(a => int.Parse(a) > 2);
foreach (var item in temp)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
//作爲委託參數的方法
//static bool MyCal(string str)
//{
// if (int.Parse(str) > 2)
// {
// return true;
// }
// return false;
//}
}
//1、聲明擴展方法中需要調用的委託類型
public delegate bool IsokDel<T>(T obj);
public static class MyListExt
{
/// <summary>
/// 擴展方法:靜態類、靜態方法、this
/// </summary>
/// <typeparam name="T">方法名後面緊跟的泛型約束是最主要的</typeparam>
/// <param name="list">this後面緊跟的類型是擴展方法要加到的類型</param>
/// <param name="del"></param>
/// <returns></returns>
public static List<T> MyFindStrs<T>(this List<T> list, IsokDel<T> del)
{
//2、根據擴展方法返回的數據類型聲明變量
List<T> result = new List<T>();
//3、遍歷使用擴展方法的類的對象
foreach (var item in list)
{
//4、調用委託參數傳遞的方法來處理每個對象
if (del(item))
{
result.Add(item);
}
}
//5、返回處理後的對象
return result;
}
}
}
四、泛型委託(Func和Action)
(一)Func
把一個委託傳到一個方法裏,然後在方法中調用
Func一共有16個重載,最後一個參數是返回值
(二)Action<int,int> 沒有返回值
五、進程、應用程序域、線程
應用程序域、進程、線程之間的關係:
一個進程可以有多個應用程序域,一個應用程序域可以執行多個線程,但同一時間線程只能在一個應用程序域中執行。
(一)進程
每個進程都有一個獨立的內存空間,進程是在應用程序級別的隔離。
//啓動IE,把傳智首頁打開
//Process process = Process.Start("iexplore.exe", "http://www.itcast.cn");
//獲得所有進程
var processes = Process.GetProcesses();
foreach (var item in processes)
{
Console.WriteLine(item.ProcessName);
}
//kill當前進程
Process p = Process.GetCurrentProcess();
Thread.Sleep(1000);
p.Kill();
(二)應用程序域
//AppDomain.Unload(AppDomain.CurrentDomain);//卸載當前AppDomain,由於是主域,不能卸載
if(AppDomain.CurrentDomain.IsDefaultAppDomain())//判斷是否爲主應用程序域
{
Console.WriteLine("這是主域");
}
//自己寫一個AppDomain
AppDomainSetup appDomainSetup = new AppDomainSetup();
appDomainSetup.LoaderOptimization = LoaderOptimization.SingleDomain;
AppDomain appDomain = AppDomain.CreateDomain("MultThread", null, appDomainSetup);
appDomain.ExecuteAssembly("MultThread.exe");
引用第三方的exe
(三)線程:
線程是操作系統執行的最小單位
線程切換19~30毫秒
1、
static void Main(string[] args)
{
#region 創建線程
//獲取當前線程
Thread mainThread = Thread.CurrentThread;
Console.WriteLine("主線程的id是:{0}", mainThread.ManagedThreadId);
//創建線程
//ThreadStart 表示在 System.Threading.Thread 上執行的方法,在此即DoWork
Thread thread = new Thread(DoWork);
thread.Name = "shit";//設置線程名
thread.IsBackground = true;
//啓動一個線程(不是真正的啓動,告訴CPU當前線程可以執行了)
thread.Start();
#endregion
Console.ReadKey();
}
static void DoWork()
{
Console.WriteLine("這是子線程在幹活呢...,它的Id是{0}",Thread.CurrentThread.ManagedThreadId);
}
線程分爲:CLR線程、操作系統線程。目前CLR線程和操作系統線程做了一一對應。
thread.Abort(); //終止線程
thread.Priority = ThreadPriority.Normal; //線程級別:微軟對windows線程分0-31級
前臺線程:線程執行完畢程序才關閉。
後臺線程:主線程關閉,後臺自動關閉。
2、帶參數的線程:
Thread thread = new Thread(a =>
{
while (true)
{
Console.WriteLine("這是子線程在幹活呢...參數值:{0},線程Id是{1}",a,Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
}
});
thread.IsBackground = true;
thread.Start(2);
Console.ReadKey();
傳遞多個參數可以用List
3、內部實現:
public class MyThread
{
public ParameterizedThreadStart callBackFunc { get; set; }
//這裏的start是委託調用的方法
public MyThread(ParameterizedThreadStart start)
{
callBackFunc = start;
}
//這裏的Start是thread.Start();
public void Start(object obj)
{
callBackFunc(obj);
}
}
六、多線程
namespace 多線程窗體間傳值
{
public delegate void TxtDel(string txt);
public partial class MainFrm : Form
{
private TxtDel SetTextDel;
public MainFrm()
{
InitializeComponent();
//允許其他線程來訪問當前線程創建的控件
//掩耳盜鈴法
//Control.CheckForIllegalCrossThreadCalls = false;
this.SetTextDel = SetText4OtherThread;
}
private void button1_Click(object sender, EventArgs e)
{
//TxtFrm txtFrm = new TxtFrm();
//txtFrm.TxtFrmDel = SaveTxt;//將SaveTxt方法傳給txtFrm的委託變量
//txtFrm.Show();
Thread thread = new Thread(() =>
{
TxtFrm txtFrm = new TxtFrm();
txtFrm.TxtFrmDel = SaveTxt;//將SaveTxt方法傳給txtFrm的委託變量
txtFrm.ShowDialog();//非模態
});
thread.Start();
}
void SaveTxt(string txt)
{
//InvokeRequired 當線程執行到此時,校驗textBox1控件是哪個線程創建的,如果是自己創建的InvokeRequired爲false,反之爲true
if (this.textBox1.InvokeRequired)
{
this.Invoke(this.SetTextDel,txt);//加上txt
}
else
{
this.textBox1.Text = txt;
}
}
public void SetText4OtherThread(string strTxt)
{
this.textBox1.Text = strTxt;
}
}
}
七、異步委託
namespace 異步委託
{
internal delegate int MyAddFunDel(int a,int b);
class Program
{
static void Main(string[] args)
{
Console.WriteLine("主線程Id:{0}",Thread.CurrentThread.ManagedThreadId);
MyAddFunDel myDel = new MyAddFunDel(AddStatic);
//myDel(1,3);
IAsyncResult delResult = myDel.BeginInvoke(3, 4, null, 2);
while (!delResult.IsCompleted)
{
//主線程幹其他事
}
int addResult = myDel.EndInvoke(delResult);
Console.WriteLine("主線程獲得結果是:{0}",addResult);
Console.ReadKey();
}
static int AddStatic(int a, int b)
{
Console.WriteLine("AddStatic執行了..."+Thread.CurrentThread.ManagedThreadId+"\r\n");
Thread.Sleep(3000);
return a + b;
}
}
}