標籤: await

在.Net 透過 Parallel 類別操控多任務平行作業(二)【軟體開發、軟體設計、系統開發、客製化軟體】

    這篇主要是再次講解 Parallel 類別並行作業的其他支援方法,主要是延續上一篇教學文章 3-1.透過 Parallel 類別操控多任務平行作業(一)。 

    這邊我將透過WPF專案實作一個使用 Parallel.ForEach 方法來支援的循環平行作業任務,它的概念就好比我們常在寫的 for(i=0;i<=10;i++)、或 foreach 迴圈,只是Parallel 類別是充分利用多個處理器、多個核心同時進行作業,執行速度當然效率就快很多。



步驟1:

在 Visual Studio 一樣建立一個WPF 專案

wpf

步驟2:

在 MainWindows.xmal 界面設計成如下結果

parellel

主要是使用了 3個 textbox 控制項,用於讓使用者輸入 資料夾路徑 、想建立的檔案數量、以及每個檔案的大小,再來使用一個 button 按鈕(開始執行 Parallel.Foreach 多任務運算), 來撰寫主要的 並行作業邏輯程式碼。


xaml 程式碼部分畫面
xaml2


步驟3:

在 Button.Click 事件撰寫主要程式碼


程式碼如下:

private void OnClick(object sender, RoutedEventArgs e)
{
     if (string.IsNullOrWhiteSpace(txtDir.Text))
     {
         MessageBox.Show(“請輸入目標存放文件的資料夾!!");
         return;
     }


    //如果目標資料夾不存在,就建立一個新的資料夾
     if (!Directory.Exists(txtDir.Text))
     {
         Directory.CreateDirectory(txtDir.Text);
     }


    int fileNum = 0;
     if (!int.TryParse(txtFileNum.Text, out fileNum))
     {
         MessageBox.Show(“請輸入檔案的數量!!"); return;
     }


    long fileSize = 0L;
     if (long.TryParse(txtSize.Text, out fileSize) == false)
     {
         MessageBox.Show(“請輸入預計每個檔案的大小!!");
         return;
     }


    //記錄要產生新的檔案名稱清單
     List<string> fileNames = new List<string>();


    for (int n = 0; n < fileNum; n++)
     {
         //檔案名稱
         string _filename = “file_" + (n + 1).ToString();


        //資料夾的絕對路徑
         string _dirpath = System.IO.Path.GetFullPath(txtDir.Text);


        //新的檔案的完整路徑
         string fullPath = System.IO.Path.Combine(_dirpath, _filename);


        //加入清單
         fileNames.Add(fullPath);
     }


    txtDisplay.Clear();


    //宣告一個Random 亂書產生器,目的待會用來產生每個檔案的隨機內容
     Random rand = new Random();


    //宣告一個 Action 委派任務,來產生每個檔案與檔案內容
     Action<string> act = (file) =>
         {
             FileInfo fileInfo = new FileInfo(file);


            //如果文件已經存在,就把它刪除
             if (fileInfo.Exists)
                 fileInfo.Delete();


            //開始進行隨機寫入內容
             byte[] buffer = new byte[fileSize];
             rand.NextBytes(buffer);


            using (FileStream fs = fileInfo.Create())
             {
                 BinaryWriter sw = new BinaryWriter(fs);
                 sw.Write(buffer);
                 sw.Close();
                 sw.Dispose();
             }


            //顯示執行結果
             string msg = string.Format(“檔案{0}已經建立完成!!\n", fileInfo.Name);
             this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => txtDisplay.AppendText(msg)));


        };


    //開始進行 Parallel 的循環平行任務作業
     Parallel.ForEach<string>(fileNames, act);


}



重點程式碼講解:

1.使用 Random rand = new Random();  ,來隨機產生每個檔案的內容。

2.宣告一個 Action 委派任務,來產生每個檔案與檔案內容。

Action<string> act = (file) =>
     {
         FileInfo fileInfo = new FileInfo(file);


        //如果文件已經存在,就把它刪除
         if (fileInfo.Exists)
             fileInfo.Delete();


        //開始進行隨機寫入內容
         byte[] buffer = new byte[fileSize];
         rand.NextBytes(buffer);


        using (FileStream fs = fileInfo.Create())
         {
             BinaryWriter sw = new BinaryWriter(fs);
             sw.Write(buffer);
             sw.Close();
             sw.Dispose();
         }


        //顯示執行結果
         string msg = string.Format(“檔案{0}已經建立完成!!\n", fileInfo.Name);
         this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => txtDisplay.AppendText(msg)));


    };

3.使用 Parallel.ForEach<string> 來開始進行 Parallel 的循環平行任務作業。

參考文章

C#多工作業與平行處理技術講解

1.透過 Thread 類別撰寫多執行緒多工作業。

2.透過 Delegate 委託支援的方法,撰寫非同步任務。

3-1.透過 Parallel 類別操控多任務平行作業(一)。

3-2. 透過 Parallel 類別操控多任務平行作業(二)。
4.使用 Task 自行控制非同步任務作業。
5.在非同步作業時,如何取消非同步任務。
6.多執行緒多任務存取相同變數,但卻各自隔離保留各自任務的值。
7.非同步存取變數的問題。
8.非同步資源鎖定解決方式。




網智數位-軟體開發(軟件開發)

針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen

在 .Net 透過 Thread 類別撰寫多執行緒多工作業【軟體開發、軟件開發、客製化軟體】

     此篇文章主要是延續上一篇 【C#多工作業與平行處理技術講解】,講解與實作如何在利用強大的 Thread 類別,使用 C# 來撰寫多執行緒多工作業功能。

在 .Net 平台中 Thread 類別位於 System.Threading 命名空間中,此類別封裝了多執行緒許多方法與功能,可以讓我們快速建立新的執行緒,進而在新的執行緒執行所需要的程式碼邏輯,在我們建立一個 Thread 的實例(Instance)時,需要透過一個委派(Delegate)與新建立的 Thread 實例和一個現有的方法(Method)進行綁定,當執行緒(Thread)啟動後,就會立即執行這個綁定的方法。

傳遞給 Thead 的建構子的委派(Delegate)有 2 種,一種是不帶任何參數的委派方法;第二種是可以帶一個 object 參數的委派方法。在我們實體化 Thread 物件後,就可以開始調用 Thread.Start()方法,來啟動執行緒(也會開始執行綁定的方法),而在執行過程隨時可以調用 Thread.Abort()方法,來強制終止執行緒的執行,不過這個 Abort()方法會引發一個 ThreadStateException 例外錯誤。

現在我就帶一個實際範例來是示範如何 用 C# 使用 Thread 類別,建立一個執行緒作業,這邊為了簡單講解觀念,我使用最簡單的 Windows Form 專案來講解。

Step 1. 透過 Visual Studio 2017(舊版本 2015/2013/2012都行啦)新增一個 Windows Form 專案

2017-07-02_23-33-29

Step 2.在 Step 1建立的 Windos  Form 專案後,會產生一個 Form1的界面表單,打開此表單,然後從工具箱拖拉一個 ProgressBar 控制箱到 Form1 畫面,並排好版面。

step2

     Step 3. 從工具箱在拖拉一個 Button 到 Form1 的畫面,並將 name 屬性命名為 btnTread , Text 修改為【Thread 執行緒 啟動】step3

 Step 4. 在 Form1.cs 後置程式碼裡,我撰寫了一個 DoWok() 方法,裡面撰寫了一下邏輯,程式碼如下:

/// <summary>
/// 此方法將會透過委派(Delegate)指定給新的執行緒(Thread)
/// </summary>
private void DoWork()
{
  int p = 0;

  while (p < 100)
  {
    p++;
    Thread.Sleep(100);

    //更新進度表
    this.BeginInvoke(new Action(() =>
    {
       this.progressBar1.Value = p;
    }));
  }

  this.BeginInvoke(new Action(delegate ()
  {
   //再次啟用按鈕狀態
   btnTreadStart.Enabled = true;
   //重設定進度表為 0
   progressBar1.Value = 0;
   //顯示執行緒已完成
   MessageBox.Show(“執行緒已完成。", “執行緒已完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
  }));

}

step4

Step 5. 在 Form1 的 Button 按鈕,雙擊滑鼠 (button1_Click),在button1_Click 事件我撰寫了 核心的 操控 Thread 程式碼

private void button1_Click(object sender, EventArgs e)
{

  //宣告一個 Thread 類別,並將在傳入 Step 4 所宣告的 DoWord 方法
  //待會 Thead 執行時,就會立即執行 DoWord 方法
  Thread newThread = new Thread(DoWork);

  //停用按鈕
  btnTreadStart.Enabled = false;

  //啟用新的執行緒
  newThread.Start();

}

step5

Step 6. Compile 編譯執行(執行F5),就可以看到結果

step 5-1

step 5-2

 

程式碼補充解釋:
因為基於執行緒的安全考量和包含使用者界面完整性,一般而言,系統是限制跨執行緒去更新修改使用者界面,所以在 Step 4 的 DoWokd方法,我透過呼叫 this.BeginInvoke() 方法傳遞一個 委派,使得可以在使用者界面的主執行緒上面進行更新使用者界面的控制箱(ProgressBar1),所以可以看到進度表一直不斷更新。

透過這一篇文章希望可以說明如何利用 Thread 類別來操作多執行作業,後續我還會抽出時間講解不同的非同步多工作業方式,分成不同的文章來一一描述。

 

 

網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen