主頁 > .NET開發 > C# 從1到Core--委托與事件

C# 從1到Core--委托與事件

2020-09-11 08:15:45 .NET開發

  委托與事件在C#1.0的時候就有了,隨著C#版本的不斷更新,有些寫法和功能也在不斷改變,本文溫故一下這些改變,以及在NET Core中關于事件的一點改變,

一、C#1.0 從委托開始

1. 基本方式

  什么是委托,就不說概念了,用例子說話,

  某HR說他需要招聘一個6年 .NET5 研發經驗的“高級”工程師,他想找人(委托)別人把這條招聘訊息發出去,這樣的HR很多,所以大家定義了一個通用的發訊息規則:

public delegate string SendDelegate(string message);

  這就像一個介面的方法,沒有實際的實作代碼,只是定義了這個方法有一個string的引數和回傳值,所有想發招聘訊息的HR只要遵守這樣的規則即可,

委托本質上是一個類,所以它可以被定義在其他類的內部或外部,根據實際參考關系考慮即可,本例單獨定義在外部,

為HR定義了一個名為HR的類:

public class HR
{
    public SendDelegate sendDelegate;
    public void SendMessage(string msg)
    {
        sendDelegate(msg);
    }
}

  HR有一個SendDelegate型別的成員,當它需要發送訊息(SendMessage)的時候,只需要呼叫這個sendDelegate方法即可,而不需要實作這個方法,也不需要關心這個方法是怎么實作的,

當知道這個HR需要發送訊息的時候,獵頭張三接了這個幫忙招人的作業,獵頭的類為Sender,他有一個用于發送訊息的方法Send,該方法恰好符合眾人定義的名為SendDelegate的發訊息規則,這有點像實作了一個介面方法,但這里不要求方法名一致,只是要求方法的簽名一致,

public class Sender
{
    public Sender(string name)
    {
        this.senderName = name;
    }

    private readonly string senderName;
    public string Send(string message)
    {
        string serialNumber = Guid.NewGuid().ToString();
        Console.WriteLine(senderName + " sending....");
        Thread.Sleep(2000);
        Console.WriteLine("Sender: " + senderName + " , Content: " + message + ", Serial Number: "  + serialNumber);
        return serialNumber;
    }
}

獵頭幫助HR招人的邏輯如下:

public void Test()
{
    //一個HR
    HR hr = new HR();

    //獵頭張三來監聽,聽到HR發什么訊息后立刻傳播出去
    Sender senderZS = new Sender("張三");
    hr.sendDelegate = senderZS.Send;

//HR遞交訊息 hr.SendMessage("Hello World"); }

獵頭將自己的發訊息方法“賦值”給了HR的SendDelegate方法,為什么可以“賦值”? 因為二者都遵守SendDelegate規則, 就像A和B兩個變數都是int型別的時候,A可以賦值給B一樣,

這就是一個簡單的委托程序,HR將招人的作業委托給了獵頭,自己不用去做招人的作業,

但經常一個招聘作業經常會有多個獵頭接單,那就有了多播委托,

2. 多播委托

 看一下下面的代碼:

public void Test()
{
    //一個HR
    HR hr = new HR();

    //獵頭張三來監聽,聽到HR發什么訊息后立刻傳播出去
    Sender senderZS = new Sender("張三");
    hr.sendDelegate = senderZS.Send;

    //快嘴李四也來了
    Sender senderLS = new Sender("李四");
    hr.sendDelegate += senderLS.Send;
//HR遞交訊息 hr.SendMessage("Hello World"); }

與之前的代碼改變不大, 只是添加了李四的方法系結,這樣HR發訊息的時候,張三和李四都會發出招人的訊息,

這里要注意李四系結方法的時候,用的是+=而不是=,就像拼接字串一樣,是拼接而不是賦值,否則會覆寫掉之前張三的方法系結,

對于第一個系結的張三,可以用=號也可以用+=(記得之前好像第一個必須用=,實驗了一下現在二者皆可),

這同時也暴露了一些問題:

  • 如果后面的獵頭接單的時候不小心(故意)用了=號, 那么最終前面的人的系結都沒有了,那么他將獨占這個HR客戶,HR發出的訊息只有他能收到,
  • 可以偷偷的呼叫獵頭的hr.sendDelegate
public void Test()
{
    //一個HR
    HR hr = new HR();

    //大嘴張三來監聽,聽到HR發什么訊息后立刻傳播出去
    Sender senderZS = new Sender("張三");
    //hr.sendDelegate -= senderZS.Send; //即使未進行過+=  直接呼叫-=,也不會報錯
    hr.sendDelegate += senderZS.Send;

    //快嘴李四也來了
    Sender senderLS = new Sender("李四");
    hr.sendDelegate += senderLS.Send;

    //移除
    //hr.sendDelegate -= senderZS.Send;

    //風險:注意上面用的符號是+=和-=   如果使用=,則是賦值操作,
    //例如下面的陳述句會覆寫掉之前所有的系結
    //hr.sendDelegate = senderWW.Send;

    //HR遞交訊息
    hr.SendMessage("Hello World");

    //風險:可以偷偷的以HR的名義偷偷的發了一條訊息    sendDelegate應該只能由HR呼叫   
    hr.sendDelegate("偷偷的發一條");

}

3. 通過方法避免風險

  很自然想到采用類似Get和Set的方式避免上面的問題,既然委托可以像變數一樣賦值,那么也可以通過引數來傳值,將一個方法作為引數傳遞,

 

    public class HRWithAddRemove
    {
        private SendDelegate sendDelegate;

        public void AddDelegate(SendDelegate sendDelegate)
        {
            this.sendDelegate += sendDelegate; //如果需要限制最多系結一個,此處可以用=號
        }

        public void RomoveDelegate(SendDelegate sendDelegate)
        {
            this.sendDelegate -= sendDelegate;
        }

        public void SendMessage(string msg)
        {
            sendDelegate(msg);
        }
    }

經過改造后的HR,SendDelegate方法被設定為了private,之后只能通過Add和Remove的方法進行方法系結,

4.模擬多播委托機制

通過上面委托的表現來看,委托就像是保存了一個相同方法名的集合 List<SendDelegate> ,可以向集合中添加或移除方法,當呼叫這個委托的時候,會逐一呼叫該集合中的各個方法,

例如下面的代碼( 注意這里假設SendDelegate只對應一個方法 ):

public class HR1
{
    public void Delegate(SendDelegate sendDelegate)
    {
        sendDelegateList = new List<SendDelegate> { sendDelegate }; //對應=
    }

    public void AddDelegate(SendDelegate sendDelegate)
    {
        sendDelegateList.Add(sendDelegate); //對應+=
    }

    public void RomoveDelegate(SendDelegate sendDelegate)
    {
        sendDelegateList.Remove(sendDelegate);//對應-=
    }

    public List<SendDelegate> sendDelegateList;

    public void SendMessage(string msg)
    {
        foreach (var item in sendDelegateList)
        {
            item(msg);
        }
    }
}

二、C#1.0 引入事件

  1.簡單事件

  如果既想使用-=和+=的方便,又想避免相關功能開閉的風險怎么辦呢?可以使用事件:

    public class HRWithEvent
    {
        public event SendDelegate sendDelegate;
        public void SendMessage(string msg)
        {
            sendDelegate(msg);
        }
    }

  只是將SendDelegate前面添加了一個event標識,雖然它被設定為public,但如下代碼卻會給出錯誤提示: 事件“HRWithEvent.sendDelegate”只能出現在 += 或 -= 的左邊(從型別“HRWithEvent”中使用時除外) 

 hr.sendDelegate = senderZS.Send;
 hr.sendDelegate("偷偷的發一條");

  2.事件的訪問器模式

   上文為委托定義了Add和Remove方法,而事件支持這樣的訪問器模式,例如如下代碼:

    public class CustomerWithEventAddRemove
    {
        private event SendDelegate sendDelegate;

        public event SendDelegate SendDelegate
        {
            add { sendDelegate += value; }
            remove { sendDelegate -= value; }
        }
        public void SendMessage(string msg)
        {
            sendDelegate(msg);
        }
    }

 

  可以像使用Get和Set方法一樣,對事件的系結與移除進行條件約束, 

  3. 控制系結事件的執行

  當多個委托被系結到事件之后,如果想精確控制各個委托的運行怎么辦,比如回傳值(雖然經常為void)、例外處理等,

第一章第4節通過一個List<SendDelegate> 模擬了多播委托的系結, 會想到如果真能回圈呼叫一個個已系結的委托,就可以精確的進行控制了,那么這里說一下這樣的方法:

 

    public class HRWithEvent
    {
        public event SendDelegate sendDelegate;
        public void SendMessage(string msg)
        {
            //sendDelegate(msg);  此處不再一次性呼叫所有
            if (sendDelegate != null)
            {
                Delegate[] delegates = sendDelegate.GetInvocationList(); //獲取所有已系結的委托
                foreach (var item in delegates)
                {
                    ((SendDelegate)item).Invoke(msg); //逐一呼叫
                }
            }

        }
    }

  這里通過Invoke方法逐一呼叫各個Delegate,從而實作對每一個Delegate的呼叫的控制,若需要異步呼叫,則可以通過BeginInvoke方法實作(.NET Core之后不再支持此方法,后面會介紹,)

((SendDelegate)item).BeginInvoke(msg,null,null);

  4. 標準的事件寫法

  .NET 事件委托的標準簽名是:

void OnEventRaised(object sender, EventArgs args);

 

  回傳型別為 void, 事件基于委托,而且是多播委托, 引數串列包含兩種引數:發件人和事件引數, sender 的編譯時型別為 System.Object

  第二種引數通常是派生自 System.EventArgs 的型別.NET Core 中已不強制要求繼承自System.EventArgs,后面會說到)

  將上面的例子修改一下,改成標準寫法,大概是下面代碼的樣子:

public class HRWithEventStandard
{
    public delegate void SendEventHandler(object sender, SendMsgArgs e);
    public event SendEventHandler Send;
    public void SendMessage(string msg)
    {
        var arg = new SendMsgArgs(msg);
        Send(this,arg); //arg.CancelRequested 為最后一個的值   因為覆寫
    }
}

public class SendMsgArgs : EventArgs
{
    public readonly string Msg = string.Empty;
    public bool CancelRequested { get; set; }
    public SendMsgArgs(string msg)
    {
        this.Msg = msg;
    }
}

 

 

三、隨著C#版本改變

1. C#2.0 泛型委托

  C#2.0 的時候,隨著泛型出現,支持了泛型委托,例如,在委托的簽名中可以使用泛型,例如下面代碼

public delegate string SendDelegate<T>(T message);

這樣的委托適用于不同的引數型別,例如如下代碼(注意使用的時候要對應具體的型別)

public delegate string SendDelegate<T>(T message);

public class HR1
{
    public SendDelegate<string> sendDelegate1;
    public SendDelegate<int> sendDelegate2;
    public SendDelegate<DateTime> sendDelegate3;
}

public static class Sender1
{
    public static string Send1(string msg)
    {
        return "";
    }

    public static string Send2(int msg)
    {
        return "";
    }
}
    
public class Test
{
    public void TestDemo()
    {
        HR1 hr1 = new HR1();
        hr1.sendDelegate1 = Sender1.Send1; // 注意使用的時候要對應具體的型別
        hr1.sendDelegate2 = new SendDelegate<int>(Sender1.Send2);
        hr1.sendDelegate3 = delegate (DateTime dateTime) { return dateTime.ToLongDateString(); };

    }
}

2. C#2.0 delegate運算子

delegate 運算子創建一個可以轉換為委托型別的匿名方法:

例如上例中這樣的代碼:

hr1.sendDelegate3 = delegate (DateTime dateTime) { return dateTime.ToLongDateString(); };

3. C#3.0 Lambda 運算式

從 C# 3 開始,lambda 運算式提供了一種更簡潔和富有表現力的方式來創建匿名函式, 使用 => 運算子構造 lambda 運算式,

例如“delegate運算子”的例子可以簡化為如下代碼:

hr1.sendDelegate3 = (dateTime) => { return dateTime.ToLongDateString(); };

 

4.C#3,NET Framework3.5,Action 、Func、Predicate

Action 、Func、Predicate本質上是框架為我們預定義的委托,在上面的例子中,我們使用委托的時候,首先要定義一個委托型別,然后在實際使用的地方使用,而使用委托只要求方法名相同,在泛型委托出現之后,“定義委托”這一操作就顯得越來越累贅,為此,系統為我們預定義了一系列的委托,我們只要使用即可,

例如Action的代碼如下:

    public delegate void Action();
    public delegate void Action<in T>(T obj);
    public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
    public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
    public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
    public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);

實際上定義了最多16個引數的無回傳值的委托,

Func與此類似,是最多16個引數的有回傳值的委托,Predicate則是固定一個引數以及bool型別回傳值的委托,

public delegate bool Predicate<T>(T obj);

 5. .NET Core 異步呼叫

第2.3節中,提示如下代碼在.NET Core中已不支持

((SendDelegate)item).BeginInvoke(msg,null,null);

 

會拋出例外:

System.PlatformNotSupportedException:“Operation is not supported on this platform.”

 

需要異步呼叫的時候可以采用如下寫法:

Task task = Task.Run(() => ((SendDelegate)item).Invoke(msg));

 

對應的 EndInvoke() 則改為: task.Wait(); 

 

 5. .NET Core的 EventHandler<TEventArgs>

.NET Core 版本中,EventHandler<TEventArgs> 定義不再要求 TEventArgs 必須是派生自 System.EventArgs 的類, 使我們使用起來更為靈活,

例如我們可以有這樣的寫法:

EventHandler<string> SendNew

 

這在以前的版本中是不允許的,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/4879.html

標籤:.NET Core

上一篇:[視頻]iNeuOS 自主可控工業互聯網一體化解決方案 整體介紹

下一篇:(1)RabbitMQ簡介與安裝

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more