瀏覽標籤:

轉載

[C#] Invoke 與 BeginInvoke 在主副線程中的執行順序和區別

在寫多執行緒時必須更新UI狀態時查到的資料,做個紀錄一下。

據msdn中介紹,它們最大的區別就是BeginInvoke屬於異步執行的。

  • Control.Invoke 方法 (Delegate)
    在擁有此控件的基礎窗口句柄的線程上執行指定的委託。
  • Control.BeginInvoke 方法 (Delegate)
    在創建控件的基礎句柄所在線程上異步執行指定委託。

總結:

以下為了方便理解,假設如下:

  1. 主線程表示Control.Invoke或Control.BeginInvoke中Control所在的線程,即創建該創建的線程。 (一般為UI線程)
  2. 支線程表示不同於主線程的調用Invoke或BeginInvoke的線程。
  3. Control的Invoke和BeginInvoke的委託方法是在主線程,即UI線程上執行。 (也就是說如果你的委託方法用來取花費時間長的數據,然後更新界面什麼的,千萬別在主線程上調用Control.Invoke和Control.BeginInvoke,因為這些是依然阻塞UI線程的,造成界面的假死)
  4. Invoke會阻塞主支線程,BeginInvoke只會阻塞主線程,不會阻塞支線程!因此BeginInvoke的異步執行是指相對於支線程異步,而不是相對於主線程異步。 (從最後一個例子就能看出,程序運行點擊button1)

 

轉載:【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

       

[Apache] 限制目錄列表

很多人設定Apache都會碰到的問題之一,就是該怎麼限制別人瀏覽自己網站的目錄。如果沒限制,目錄內所有檔案的位置都會被看到,有更新但還未公開在首頁的檔案就會被看到。

  1. 找到路徑/etc/apache2/sites-available
  2. 找到自己網站的conf設定檔
  3. Directory節點的Options拿掉Indexes
    範例如下:

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
    	#管理者郵箱 
    	ServerAdmin [email protected]
    	#網站名稱 
    	ServerName blog.exfast.me
    	#網站別名
    	ServerAlias blog.exfast.me
    	#網站的根目錄
    	DocumentRoot /var/www/blog
    	#網站的錯誤日誌檔存放的位置與檔名
    	ErrorLog /var/log/error/blog.log
    	#網站日誌檔存放的位置與檔名
    	CustomLog /var/log/access/blog.log combined
    	<Directory "/var/www/blog/">
    		AllowOverride All
    		Options FollowSymLinks MultiViews
    	</Directory>
    </VirtualHost>
    </IfModule>

     

 

 

原文:Apache設定限制目錄瀏覽的方法

       

[C#] Convert(轉型)、Parse(強制轉型)、TryParse(安全轉型)與運算子轉型的差別、效能

最近再磨練基本功的時候複習了常用到的「轉型」,找一找資料後統整了一下才比較搞懂這些差異。

轉型別基本上分為下列五種:

  1. Convert(轉型)
    Convert.ToInt32("5.5");
  2. Parse(強制轉型)
    (int)(5.5);
    int.Parse("5.5");
  3. TryParse(安全轉型)
    int i = 0;
    int.TryParse("5.5", out i)
  4. 運算子 – as
    CustomModel model = obj as CustomModel
  5. 運算子 – is
    CustomModel model = obj is CustomModel

根據參考資料差異如下:

  1. Convert 是將值轉換成最接近的 32 位元帶正負號的整數
    Console.WriteLine(Convert.ToInt32("4.5")); //result = 4
    Console.WriteLine(Convert.ToInt32("4.51"));//result = 5
    Console.WriteLine(Convert.ToInt32("5.4")); //result = 5
    Console.WriteLine(Convert.ToInt32("5.5")); //result = 6
  2. Parse 則是無條件捨去( long、float、double、或 decimal )
    Console.WriteLine((int)(4.5)); //result = 4
    Console.WriteLine((int)(4.51));//result = 4
    Console.WriteLine((int)(5.4)); //result = 5
    Console.WriteLine((int)(5.5)); //result = 5
    
  3. TryParse 會回傳一布林值來判斷是否轉換成功
    string s1 = "1234"; 
    string s2 = "1234.65"; 
    string s3 = null; 
    string s4 = "123456789123456789123456789123456789123456789"; 
    bool success = false;    
    int result = 0; 
    success = Int32.TryParse(s1, out result); //-- success => true;  result => 1234 
    success = Int32.TryParse(s2, out result); //-- success => false; result => 0 
    success = Int32.TryParse(s3, out result); //-- success => false; result => 0 
    success = Int32.TryParse(s4, out result); //-- success => false; result => 0
  4. as 若轉型失敗會回傳null,且只能用於參考類型,不能應用於值類型(除非是Nullable的值類型)。
    CustomModel model = obj as CustomModel;
    if(model  != null)
    {
        //轉型成功
    }
    else
    {
        //轉型失敗
    }
  5. is 若轉型失敗則會跳Exception
    try
    {
        CustomModelt = obj is CustomModel;
    }
    catch
    {
        //轉型失敗
    }

2017/09/24 更新

(Net Core 2.0)效能上 Parse > TryParse > Convert。

測試程式碼:

class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            Convert.ToInt32(i.ToString());
        }
        sw.Stop();

        Console.WriteLine(string.Format("Convert.ToInt32 = {0} ms", sw.ElapsedMilliseconds));
        sw.Reset();

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            int.Parse(i.ToString());
        }
        sw.Stop();

        Console.WriteLine(string.Format("int.Parse = {0} ms", sw.ElapsedMilliseconds));
        sw.Reset();

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            int.TryParse(i.ToString(), out int tmp);
        }
        sw.Stop();

        Console.WriteLine(string.Format("int.TryParse = {0} ms", sw.ElapsedMilliseconds));
        sw.Reset();

        object model = new TestModel
        {
            Tmp = 100
        };

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            var tmp = model as TestModel;
        }
        sw.Stop();

        Console.WriteLine(string.Format("as = {0} ms", sw.ElapsedMilliseconds));
        sw.Reset();

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            var tmp = model is TestModel;
        }
        sw.Stop();

        Console.WriteLine(string.Format("is = {0} ms", sw.ElapsedMilliseconds));
        sw.Reset();

        Console.ReadKey();
    }

    public class TestModel
    {
        public int Tmp { get; set; }
    }
}

 

參考:

  1. Convert(轉型)與Int32(強制轉型)的差別、效能
  2. [C#]Convert.ToInt32()與int.Parse()的差別
  3. [C#]Convert、Parse、TryParse 差異
  4. [C#]Effective C# 條款三: 運算子is或as優於強制轉型
       

[轉載] 系統架構設計

來源:[鐵人30天]當ASP.NET MVC 遇見 Angular.js MVC 客戶管理系統(3) – 系統架構設計

* 為何要分層架構規劃

分層的重要性,也是寫程式幾年後才真的領悟,ASP時代那種義大利麵式的寫法(html、Script、後端程式、SQL程式全混再一起),接著WebForm CodeBind將前後端拆後,再到現在慣用的MVC,深深覺得”關注點分離”這的確是一件很重要的事,目前開發習慣,即使專案在小,也會整理出自己的三層架構起手式,如果是更大型專案,就會再更細分。

架構圖:

_thumb3

各分層介紹:

  • DAL(Data Access Layer) : 有關SQL語法、EntityFream資料庫溝通,都會在此層。
  • BLL(Business Login Layer):資料流從DB或從User輸入後,一定會有一些邏輯判斷,該商業邏輯流程都會寫在此層
  • UI(User Interface):有關Web專案、Web API(Web Service)、Apps 都會在此層
  • Domain Entity : 裡面會有定義ViewModel Class,用來貫穿三個分層
  • Resources:用來放一些資源檔 … e.g 多國語系檔
  • Utility : 用來放置一些共用函示庫 … 如加解密

整個專案建立完如下圖:

1_thumb4

       

[NG2] 了解 Angular CLI 產生的專案目錄結構

來源:[Angular2速成班]了解Angular CLI產生的專案目錄結構

透過Angular CLI我們可以很容易的建立一個具有一致性的專案架構,今天我們就來簡單介紹一下使用ng new指令產生的專案目錄內容,讓以後在開發Angular2專案時可以很清楚知道檔案的存放位置。

 

/protractor.conf.js
/e2e

e2e這個資料夾主要用來存放end to end的測試案例,Angular2 CLI產生的專案會使用protractor來進行end to end測試,protractor是angular開發團隊推出的end to end測試框架,自然跟Angular2最match啦!關於測試相關的設定,則是存放在/protractor.conf.js這個檔案中。
我們可以透過 ng e2e 指令來進行end to end的測試。

 

/node_modules

我想不用介紹太多,只要對前端工程有一定熟悉的人都知道這個目錄是用來幹嘛的,簡單來說就是所有相關會用到的模組都在這個資料夾裡啦!

 

/src

這個目錄非常重要,因為它就是我們未來所有撰寫的程式碼會存放的目錄,所以以後會常常近來這個目錄操作哩;當我們使用Angular CLI產生需要的檔案時,也都會存放在這個目錄之中。

 

/.editorconfig

EditorConfig是專門給IDE看的一個檔案,用來告知IDE該如何調整專案目錄下的程式碼風格,如果IDE支援的話,就能夠針對.editorconfig這個檔案的設定來調整你的程式碼風格,如果不支援的話,這個檔案就可有可無囉。

如果是使用Visual Studio Code開發的話,可以安裝EditorConfig for VS Code這個外掛來讓它支援EditorConfig

 

./angular-cli.json

給Angular CLI看的設定檔,基本上就是一些目錄及打包程式時的設定,如果團隊開發對於檔案存放目錄有特別設定的需求,或打包程式時需要引入額外的程式庫,都可以在這個檔案中設定。

 

./karma.conf.js

Angular CLI產生的專案使用Karma作為unit test的測試框架,因此相關設定都寫在這裡囉。要進行unit test時,可以使用 ng test 指令。

 

./tslint.json

用來針對TypeScript的程式撰寫風格進行規範(linter)的設定檔,就如同CSSLint、ESLint等,我們也可以透過TSLint來檢查TypeScript的coding style,只要執行 ng lint 來檢查就可以了。

       

[Regex] 知道這20個規則運算式,能讓你少寫1,000行代碼(2017/04/22)

轉載:知道这20个正则表达式,能让你少写1,000行代码

 

規則運算式,一個十分古老而又強大的文本處理工具,僅僅用一段非常簡短的運算式語句,便能夠快速實現一個非常複雜的業務邏輯。熟練地掌握規則運算式的話,能夠使你的開發效率得到極大的提升。

規則運算式經常被用於欄位或任意字串的校驗,如下面這段校驗基本日期格式的JavaScript代碼:

var reg = /^(\\d{1,4})(-|\\/)(\\d{1,2})\\2(\\d{1,2})$/; 
var r = fieldValue.match(reg); 
if(r==null)alert('Date format error!');

下面是技匠整理的,在前端開發中經常使用到的20個規則運算式。

 

  1. 校驗密碼強度
    密碼的強度必須是包含大小寫字母和數位的組合,不能使用特殊字元,長度在8-10之間。

    ^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
  2. 校驗中文
    字串僅能是中文。

    ^[\\u4e00-\\u9fa5]{0,}$
  3. 由數位、26個英文字母或底線組成的字串
    ^\\w+$
  4. 校驗E-Mail 地址
    同密碼一樣,下面是E-mail地址合規性的正則檢查語句。

    [\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?
  5. 校驗身份證號碼
    下麵是身份證號碼的正則校驗。15 或 18位。

    • 15位
      ^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$
    • 18位
      ^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$
  6. 校驗日期
    “yyyy-mm-dd“ 格式的日期校驗,已考慮平閏年。

    ^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$
  7. 校驗金額
    金額校驗,精確到2位小數。

    ^[0-9]+(.[0-9]{2})?$
  8. 校驗手機號下麵是國內 13、15、18開頭的手機號規則運算式。(可根據目前國內收集號擴展前兩位開頭號碼)
    ^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$
  9. 判斷IE的版本IE目前還沒被完全取代,很多頁面還是需要做版本相容,下面是IE版本檢查的運算式。
    ^.*MSIE [5-8](?:\\.[0-9]+)?(?!.*Trident\\/[5-9]\\.0).*$

     

  10. 校驗IP-v4地址IP4 正則語句。
    \\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b

     

  11. 校驗IP-v6地址IP6 正則語句。
    (([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

     

  12. 檢查URL的首碼應用開發中很多時候需要區分請求是HTTPS還是HTTP,通過下面的運算式可以取出一個url的首碼然後再邏輯判斷。
    if (!s.match(/^[a-zA-Z]+:\\/\\//))
    {
        s = 'http://' + s;
    }

     

  13. 提取URL連結下面的這個運算式可以篩選出一段文本中的URL。
    ^(f|ht){1}(tp|tps):\\/\\/([\\w-]+\\.)+[\\w-]+(\\/[\\w- ./?%&=]*)?

     

  14. 檔路徑及副檔名校驗驗證windows下檔路徑和副檔名(下面的例子中為.txt文件)
    ^([a-zA-Z]\\:|\\\\)\\\\([^\\\\]+\\\\)*[^\\/:*?"<>|]+\\.txt(l)?$

     

  15. 提取Color Hex Codes有時需要抽取網頁中的顏色代碼,可以使用下面的運算式。
    ^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$

     

  16. 提取網頁圖片假若你想提取網頁中所有圖片資訊,可以利用下面的運算式。
    \\< *[img][^\\>]*[src] *= *[\\"\\']{0,1}([^\\"\\'\\ >]*)

     

  17. 提取頁面超連結提取html中的超連結。
    (<a\\s*(?!.*\\brel=)[^>]*)(href="https?:\\/\\/)((?!(?:(?:www\\.)?'.implode('|(?:www\\.)?', $follow_list).'))[^"]+)"((?!.*\\brel=)[^>]*)(?:[^>]*)>

     

  18. 查找CSS屬性通過下面的運算式,可以搜索到相匹配的CSS屬性。
    ^\\s*[a-zA-Z\\-]+\\s*[:]{1}\\s[a-zA-Z0-9\\s.#]+[;]{1}

     

  19. 抽取注釋如果你需要移除HMTL中的注釋,可以使用如下的運算式。
    <!--(.*?)-->

     

  20.  匹配HTML標籤通過下面的運算式可以匹配出HTML中的標籤屬性。
    <\\/?\\w+((\\s+\\w+(\\s*=\\s*(?:".*?"|'.*?'|[\\^'">\\s]+))?)+\\s*|\\s*)\\/?>

     

  21. 6-20位英數混合字,不可以輸入空白字元、特殊符號。(2017/04/22)
    /^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z0-9]{6,20}$/

 

       

[C#][ASP.NET WebAPI] 修改預設回傳格式為Json

最近在玩ASP.NET Web API,他不但支援Json也支援Xml,但預設回傳的格式是Xml怎麼辦?

 

檔案位置:~/App_Start/WebApiConfig.cs

//預設回傳Json
MediaTypeHeaderValue appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

 

參考:

       

[C#] 利用 interface(介面) abstract(抽象) override(覆寫) inherit(繼承) 實作簡單範例

來源:

  1. (原創) interface和abstract class有何不同? (C/C++) (.NET) (C#)
  2. [C#] abstract 和 virtual 函數的差異

 

這篇真的寫得很棒,大家一定要點進去看看,並自己動手寫Code !!
而我自己寫一篇只是為了建檔,方便日後自己觀看用,裡面的Code都是基於上面教學文寫的,自己只是加了一個AutoDoor的功能而已。

 


 

  1. 建立一個abstract的Door類別,裡面有Open(開門)與Close(關門)這兩個虛擬方法可以用
    abstract class Door
    {
        public virtual void Open()
        {
            Console.WriteLine("Open Door");
        }
        public virtual void Close()
        {
            Console.WriteLine("Close Door");
        }
    }
    

     

  2. 建立一個HorizontalDoor類別,它繼承了原先的Door,所以它也有Open與Close這兩個方法可以用
    class HorizontalDoor : Door { }
    

     

  3. 建立一個VerticalDoor類別,它也繼承了Door,可是我在裡面override了原先的Open與Close,另外實作其方法
    class VerticalDoor : Door
    {
        public override void Open()
        {
            Console.WriteLine("Open vertically");
        }
        public override void Close()
        {
            Console.WriteLine("Close vertically");
        }
    }
    

     

  4. 建立一個IAlarm介面,裡面定義了Alert這個方法
    interface IAlarm
    {
        void Alert();
    }
    

     

  5. 建立一個Alarm類別,它繼承了IAlarm,並在裡面實作Alert
    class Alarm : IAlarm
    {
        public void Alert()
        {
            Console.WriteLine("Ring ~~");
        }
    }
    

     

  6. 建立一個AlarmDoor類別,它繼承了Door,同時在裡面使用了Alarm類別的Alert方法
    class AlarmDoor : Door
    {
        private IAlarm _alarm;
    
        public AlarmDoor()
        {
            _alarm = new Alarm();
        }
    
        public void Alert()
        {
            _alarm.Alert();
        }
    }
    

     

  7. 建立一個AutoAlarmDoor類別,它繼承了AlarmDoor,並覆寫了原本的Open方法,裡面呼叫base.Open方法並接著呼叫Alert方法
    class AutoAlarmDoor : AlarmDoor
    {
        public override void Open()
        {
            base.Open();
            Alert();
        }
    }
    

     

  8. 建立一個DoorController類別,這個類別是用來控制管理所有的Door
    class DoorController
    {
        protected List<Door> _dootList = new List<Door>();
    
        public void AddDoor(Door Door)
        {
            _dootList.Add(Door);
        }
    
        public void OpenDoor()
        {
            foreach (var item in _dootList)
            {
                item.Open();
            }
        }
    }
    

     

  9. 完成 !!
    static void Main(string[] args)
    {
        DoorController dc = new DoorController();
        dc.AddDoor(new HorizontalDoor());
        dc.AddDoor(new VerticalDoor());
        dc.AddDoor(new AlarmDoor());
        dc.AddDoor(new AutoAlarmDoor());
    
        dc.OpenDoor();
    
        Console.ReadLine();
    }

     

  10. 執行結果
    2016-09-07 23_06_31-file____C__Users_Minsheng_Desktop_ConsoleApplication_Door_ConsoleApplication_Doo

 

  • 注意事項
    1. abstract method 不會有程式內容
    2. abstract method 繼承後,一定要 override
    3. virtual method 一定要有程式內容
    4. 宣告為 virtual 的 method,繼承後才可以進行 override
    5. 設定為 virtual 的 method,沒有一定要 override

 

       

[MSSQL] SQL Server Management Studio 連線非預設 1433 port 埠號

參考:SQL Server 透過 TCP/IP 遠端連線時如何使用非 1433 埠號

 

未命名

自從把SQL Server放到公用網路上的時候,就常常被人暴力破解Try我的密碼,雖然不至於被猜到,但是看了總是不太開心,於是乎就把預設的Port修改掉了,卻發生使用SQL Server Management Studio無法連線的問題,之前用MySQL時格式不外乎就是在後面加上:port但轉來MSSQL卻發生無法連線的問題…

 

爬了一下文才發現,使用ip,port(127.0.0.1,4321)這種格式就可以正常連線囉!
2016-08-20 18_18_00-連接到伺服器

       
  • 1
  • 2