2019年3月1日 星期五

C# 執行緒(Thread)參數傳遞方式

在此介紹幾種執行緒中參數該如何傳遞:

  • 利用建構子的方式,new class時把參數帶入
  • 利用Start接收object單個參數的方式傳遞參數
  • 利用lambda表達式調用方法

以下為執行結果

以下為程式碼:

using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            /** *******************
             * Thread的傳遞參數
             * ********************/

            //方法一:使用建構子方式
            var sample = new ThreadSample(3);
            var threadOne = new Thread(sample.CountNumbers);
            threadOne.Name = "One";
            threadOne.Start();
            threadOne.Join();

            //方法二:利用Start接收object單個參數的方式傳遞參數,裡頭再去轉型
            var threadTwo = new Thread(Count);
            threadTwo.Name = "Two";
            threadTwo.Start(4);
            threadTwo.Join();

            //方法三:利用lambda表達式
            var threadThree = new Thread(() => CountNumbers(5));
            threadThree.Name = "Three";
            threadThree.Start();
            threadThree.Join();

            //觀察列印出來的值會發現都是20
            int i = 10;
            var threadFour = new Thread(() => PrintNumber(i));
            i = 20;
            var threadFive = new Thread(() => PrintNumber(i));
            threadFour.Start();
            threadFive.Start();
        }
        static void Count(object iterations)
        {
            CountNumbers((int)iterations);
        }
        static void PrintNumber(int number)
        {
            Console.WriteLine(number);
        }
        static void CountNumbers(int iterations)
        {
            for (int i = 0; i <= iterations; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
                Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
            }
        }
    }

    class ThreadSample
     {
        private readonly int _iterations;

        public ThreadSample(int iterations)
        {
            _iterations = iterations;
        }
        public void CountNumbers()
        {
            for(int i=0;i<= _iterations;i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
                Console.WriteLine($"{Thread.CurrentThread.Name} prints {i}");
            }
        }
         
     }
}

2019年2月27日 星期三

C# 執行緒(Thread)的優先序(Priority)探討

執行緒的優先序,一般預設是Normal,設定它的優先序可以決定占用CPU的時間。

以下我們可以觀察到一般的執行結果如下:
  • 在多核心的情況下:優先序較高者,計算的count數較高
  • 在單核心的情況下:優先序較高者先執行,優先序低者還沒執行Stop已經被呼叫了


程式代碼如下:

using System;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            /** *******************
             * 測試Thread的優先序
             * ********************/
            Console.WriteLine($"priority: {Thread.CurrentThread.Priority}");
            Console.WriteLine("----");
            Console.WriteLine($"multi-core:");
            RunThread();
            Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.WriteLine("----");
            Console.WriteLine($"single-core:");
            //讓系統只在單一CPU上運行
            Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
            RunThread();
        }

        static void RunThread()
        {
            var sample = new ThreadSample();
            var t1 = new Thread(sample.CountNumbers);
            var t2 = new Thread(sample.CountNumbers);

            t1.Name = "Thread One";
            t2.Name = "Thread Two";
            //指定t1有最高優先權
            t1.Priority = ThreadPriority.Highest;
            //指定t2有最低優先權
            t2.Priority = ThreadPriority.Lowest;

            t1.Start();
            t2.Start();

            Thread.Sleep(TimeSpan.FromSeconds(2));
            sample.Stop();
        }
    }

    class ThreadSample
     {
        private bool _isStop = false;
        public void Stop()
        {
            _isStop = true;
        }
        public void CountNumbers()
        {
            long count = 0;
            while(!_isStop)
            {
                count++;
            }
            //看執行緒記算了多少count,觀察優先序的影響
            Console.WriteLine($@"{Thread.CurrentThread.Name}
with {Thread.CurrentThread.Priority} priority
has a count = {count}");
        }
         
     }
}

C# 執行緒(Thread)初探

Thread的概念就不多說了,一個CPU只能執行一個Thread的任務,所以基本上在多核心的CPU上才能看見功效,否則也只是兩個Threads在同一個CPU上交錯執行而已。

以下是C#上Thread最最基礎的部分,包含

  • new thread:新增執行緒
  • start:啟動執行緒
  • sleep:暫停執行緒
  • join:讓主執行緒等待執行緒執行結束
  • abort:終止執行緒
  • ThreadState:查看狀態轉移

以下是程式碼,可以根據顏色自行測試。


using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            /** *******************
             * 使用Thread
             * ********************/
            //先起一個Thread,委託執行PrintNumbers
            Thread t = new Thread(PrintNumbers);
            //開始執行
            t.Start();
            //直接呼叫,此時並不會等t執行完
            PrintNumbers();


            /** *******************
             * 使用Sleep暫停Thread
             * ********************/
            //先起一個Thread,委託執行PrintNumbersWithDelay
            Thread t1 = new Thread(PrintNumbersWithDelay);
            //開始執行
            t1.Start();
            //直接呼叫,此時並不會等t1執行完
            PrintNumbers();


            /** *******************
             * 使用Join讓主程序等待Thread
             * ********************/
            //先起一個Thread,委託執行PrintNumbersWithDelay
            Thread t2 = new Thread(PrintNumbersWithDelay);
            //開始執行
            t2.Start();
            //測試使用Join等待t2程序完成後,才繼續繼續執行主程序PrintNumbers()
            t2.Join();
            PrintNumbers();


            /** *******************
             * 使用Abort讓thread終止執行
             * ********************/
            //先起一個Thread,委託執行PrintNumbersWithDelay
            Thread t3 = new Thread(PrintNumbersWithDelay);
            //開始執行
            t3.Start();
            //讓執行緒暫停比較容易看出差異
            Thread.Sleep(TimeSpan.FromSeconds(5));
            //測試使用Abort終止t3
            t3.Abort();
            PrintNumbers();


            /** *******************
             * 觀察Thread的Status
             * ********************/
            Thread t4 = new Thread(PrintNumbersWithStatus);
            Thread t5 = new Thread(DoNothing);
            //Unstarted
            Console.WriteLine(t4.ThreadState.ToString());
            //開始執行
            t4.Start();
            t5.Start();
            for (int i = 0; i < 10; i++)
            {
                //觀察t4的狀態變化
                Console.WriteLine(t4.ThreadState.ToString());
            }
            //讓執行緒暫停比較容易看出差異
            Thread.Sleep(TimeSpan.FromSeconds(6));
            //使用Abort終止t4
            t4.Abort();
            Console.WriteLine("t4 has been aborted.");
            Console.WriteLine("t4:" + t4.ThreadState.ToString());
            Console.WriteLine("t5:" + t5.ThreadState.ToString());
        }

        static void PrintNumbers()
        {
            Console.WriteLine("Start");
            for(int i=0;i<10;i++)
            {
                Console.WriteLine(i);
            }
        }

        static void PrintNumbersWithDelay()
        {
            Console.WriteLine("Start");
            for (int i = 0; i < 10; i++)
            {
                //暫停兩秒後才繼續執行
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine(i);
            }
        }

        static void PrintNumbersWithStatus()
        {
            Console.WriteLine("Status:"+Thread.CurrentThread.ThreadState.ToString());
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(TimeSpan.FromSeconds(2));
                Console.WriteLine(i);
            }
        }

        static void DoNothing()
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    }

}


2019年2月20日 星期三

單純使用JavaScript做到發撲克牌的效果

今天使用javascript,做了一個發牌的功能,想法是這樣的:

  1. 初始化撲克牌,有四個花色,各13張牌。
  2. 根據玩家數量,點選發牌按鈕後,做到自動發牌。
  3. 點選按鈕後的動作=>3-1洗牌、3-2根據玩家數量開始發牌
  4. 結果呈現

以下是程式碼:

<html>
<head>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script type="text/javascript">

        //1.先初始化撲克牌
        var suit = ["clubs", "hearts", "diamonds", "spades"];
        var number = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"];
        var poker = [];

        $(document).ready(function () {
            for (var i = 0; i < suit.length; i++) {
                for (var j = 0; j < number.length; j++) {
                    var item = [suit[i], number[j]];
                    poker.push(item);
                }
            }
        });

        //洗牌
        function shuffle(a, b) {
            var num = Math.random() > 0.5 ? -1 : 1;
            return num;
        };

        //2.點選發牌觸發事件
        function deal() {
            //3-1先洗牌
            poker.sort(shuffle);
            //取得玩家數量
            var players = $("input[name='players']:checked").val();
            var playercards = [];
            var pokerarea = document.getElementById("pokerarea");
            pokerarea.innerHTML = "";
            //初始化存放玩家發到牌的陣列
            for (var j = 0; j < players; j++) {
                playercards[j] = [];
            }
            //3-2開始發牌
            for (var i = 0; i < poker.length; i++) {
                var x = i % players;
                playercards[x].push(poker[i]);
            }
            //4.動態產生DOM
            var top = 0;
            var left = 0;
            for (var j = 0; j < players; j++) {
                if (document.getElementById('issort').checked) playercards[j].sort();
                var div = document.createElement("div");
                for (var i = 0; i < playercards[j].length; i++) {
                    var img = document.createElement("img");
                    img.setAttribute("id", playercards[i]);
                    img.setAttribute("style", "position:absolute;top:" + top + "px;left:" + left + "px");
                    img.src = playercards[j][i][0] + "/" + playercards[j][i][1] + ".gif";
                    div.appendChild(img);
                    left = left + 20;
                }
                pokerarea.appendChild(div);
                top = top + 120;
                left = 0;
            }
        }

    </script>
</head>
<body>
    玩家:
    <input type="radio" name="players" value="2"> 2
    <input type="radio" name="players" value="3"> 3
    <input type="radio" name="players" value="4" checked> 4
    <input type="radio" name="players" value="5"> 5
    <input type="radio" name="players" value="6"> 6 人  

    是否根據花色排序:
    <input type="checkbox" id="issort">
    <input type="button" value="發牌" onclick="deal()">
    <br>
    <br>
    <div id="pokerarea" style="position:relative;">
    </div>
</body>
</html>

執行結果如下圖

原始碼下載:
點此下載

2018年10月31日 星期三

導入Progress®Telerik® UI for ASP.NET MVC

https://docs.telerik.com/aspnet-mvc/introduction

系統環境需求
  • .NET Framework 3.5 and later
  • ASP.NET MVC 3 and later
  • Visual Studio 2010 and later
  • IIS 5 and later
  • C# / VB.NET
  • SharePoint 2010 and later
系統導入步驟

1.官網下載套件後解壓縮得到檔案。
2.專案加入參考:kendo.mvc.dll
3.加入javascript參考(必須先引用jquery)
  • kendo.all.min.js
  • kendo.timezones.min.js(不一定需要,除非你要開發scheduler功能)
  • kendo.aspnetmvc.min.js
4.加入css參考
  • kendo.common-bootstrap.min.css
  • kendo.bootstrap.min.css
5. 更新web.config
在namespace區塊中加入 <add namespace="Kendo.Mvc.UI" />
--------以上是手動加入------


--------你也可以這樣做------
1. 用NuGet:Install-Package Kendo.Mvc -Version 版本號
2. 用vs的擴充功能和更新找到kendo套件

2018年9月30日 星期日

Flask Jinja2

Jinja2是Flask默認支持的模版引擎,主要作用是渲染模板。

在layout.html中,用{% block body %}和{% endblock %}來綁訂其他頁面內容。所以在這個網頁中,我們可以制定網頁中共用的模板。

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>MyFlaskApp</title>
</head><body>{% block body %} {% endblock %}
</body></html>

另外我們在home.html指定引用layout.html,並撰寫{% block body %}和{% endblock %}之間的網頁內容。

{% extends 'layout.html' %}  #

{% block body %}
 Home Welcome!
{% endblock %}

最後透過flask route造訪home.html時,會先執行layout.html文件,執行完畢後會帶出home.html內容。我們可以看執行結果如下:








如果你要在layout.html中嵌入其他頁面,可以用{% include '網頁來源' %}這個語法來完成。
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>MyFlaskApp</title></head><body>{% include './includes/menu.html' %}
{% block body %} {% endblock %}
</body></html>

其中menu.html如下:
<a href="https://www.jetbrains.com/pycharm"> pycharm </a> <br><a href="http://flask.pocoo.org/"> flask </a> <br>

執行結果就可以看到layout.html已經嵌入menu.html。



2018年9月24日 星期一

Flask Route

Flask是python網站開發微框架。


File->Setting-選到自己的Project->Project Interpreter-> ┼ (右邊加號)>搜尋flask->install package
  • Flask中的路由
新增一檔案名為app.py,import Flask
#making available the code you need to build web apps with flask
from flask import Flask, render_template
# create an instance of the Flask class for our web app
app = Flask(__name__)


# when the user navigates to localhost:5000, 
# the home function will run and it will return its output on the webpage.
@app.route("/")def hello():
    # return "<h3>Hello World! 123</h3>"
    # 利用render_template()導到html檔案,
    # 要注意的是:1.需import render_template 2.該html檔要放在根目錄的Templates目錄之下    return render_template("home.html")

# If the input to the route method was something else, let’s say ‘/abc/’, 
# the function output would be shown when the user visited localhost:5000/abc/
@app.route("/abc")def hello2():
    return 'Hello World! 45678'

# 執行該application,當debug=True,開發環境中則不必重啟server,重新整理網頁即可
app.run(debug=True) 



點選RUN執行,即可看到結果。