Web Service
Web Service 所建立的資料並不是全部都能在網路上傳遞,因此使用 Web Service 實應注意。以下是在 .Net 中常用且可在網路上傳遞的資料型別:- 基本資料型別(bool、string、DataTime、int 以及所有數值類型的資料型別)
- 列舉資料型別(透過 enum 所定義的資料型別)
- 以 XML 結構描述的資料
- DataSet 物件(DataSet 物件是利用 XML 來描述的因此可以傳遞)
- 上述資料型別所組成的陣列
Web Service 物件的方法必須在程式碼前加上:
- [WebMethod]
- public
.NET 呼叫(啟動)外部程式
如何利用 C# 執行外部程式
System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.EnableRaisingEvents=false; proc.StartInfo.FileName="filename"; // 檔案名稱 proc.Start();
除了使用 System.Diagnostics.Process 以外,傳統的 Shell 方法也可以,不過必須注意存在的風險:
一般的命令提示列指令大多會存取系統資源,要使用 Web 應用程式呼叫命令列程式,可能會因為 Web 程式權限不足無法無法執行,也可能因為開放權限而造成安全漏洞。
這問題有兩種解法:
- 將呼叫命令列的程式獨立寫成元件 將元件加入 COM+,若是 Windows 2003 可以設定成以 Windows service 方式執行。在 COM+ 上設定 Web 應用程式的存取權。
- Web Service 將此一 Web services 獨立一個應用程式集區,並只提供本機呼叫,授與一個較高的權限執行系統命令。
重新導向輸出
當一個程式啟動時,作業系統會相對應的產生一個行程,而我們可以經由 process ID 和行程名稱來辨識該行程。
在 .NET 中,Process 元件可以用來產生、刪除、暫停一個新的行程;我們也可以經由下面的屬性來取的相關的資訊:
- NonpagedSystemMemorySize:
- PagedMemorySize:
- PagedSystemMemorySize:
- PeakPagedMemorySize:
- PeakVirtualMemorySize:
- PeakWorkingSet
- PriorityClass
- PrivateMemorySize
- PrivilegedProcessorTime
Process 元件中,包含了靜態和實例方法。比較常用的靜態方法如:
- EnterDebugMode:讓該行程進入除錯模式
- GetCurrentProcess:回傳目前正在執行的行程
- GetProcessById:回傳指定的行程 ID 參考
- GetProcesses:回傳目前機器上所有執行的行程所組成的陣列
- Start:啟動一個新行程
Process 類別方法:
- Close:釋放 Process 元件所使用的相關資源
- Kill:終止正在執行的行程
- CloseMainWindow:藉由傳送訊息到行程所在的主視窗來結束該行程
Process 類別屬性:
- Responding:取得目前行程的狀態;true 表示還在執行中,false 代表無回應
- StandardError:取得行程的標準錯誤輸出的檔案描述子(file descriptor)好將其重新導向到 Stream Reader,以檔案的方式來讀取之
- StandardInput:取得行程的標準輸入的檔案描述子(file descriptor)好將其重導向,使得我們寫入資料到行程就好像寫資料到 StremWriter 一樣
- StandardOutput:類似標準錯誤輸出,但是用來讀取行程的標準輸出
- StartInfo:在行程啟動前,傳遞初始化參數給行程的屬性;若是在行程啟動後才改變行程的參數,將不會有任何影響
要重新導向標準的輸出入,首先必須初始化一個 ProcessStartInfo 類別,並以我們想要啟動的應用程式名稱作為該類別的建構子引數,並設定一些參數,最後把它傳遞給 Process 實例:
ProcessStartInfo psI = new ProcessStartInfo("cmd");
psI.UseShellExecute 屬性必須設定為 false,以便重新導向 StandardInput 等其它標準輸出入。所以,下面的這些屬性
psI.RedirectStandardInput psI.RedirectStandardOutput psI.RedirectStandardError
都被設定為 true。
為了避免顯示命令列提示字元那個惱人的視窗,我們也將 psI.CreateNoWindow 屬性設定為 true,因此 cmd 將不會顯示視窗。最後,設定 p.StartInfo 為剛剛建立的 ProcessStartInfo 實例。
為了能夠擷取 p.StandardInput、p.StandardOutput 和 p.StandardError,我們必須取得檔案描述子(StreamReaders 和 StreamWriter 類別),來讀取 StandardOutput、StandardError 和寫入 StandardInput;就跟我們讀取或寫入檔案一樣的方式。當我們關閉 p.StandardInput 檔案描述子時,cmd 行程也會被終止。
最後,我們讀取 p.StandardOutput 和 p.StandardError 檔案描述子的內容到 text box。
下面是整個完整範例:
private void start() { Process p = new Process(); StreamWriter input; StreamReader output; StreamReader err; ProcessStartInfo psI = new ProcessStartInfo("cmd"); psI.UseShellExecute = false; psI.RedirectStandardInput = true; psI.RedirectStandardOutput = true; psI.RedirectStandardError = true; psI.CreateNoWindow = true; p.StartInfo = psI; p.Start(); input = p.StandardInput; output = p.StandardOutput; err = p.StandardError; input.AutoFlush = true; if (tbComm.Text != "") input.WriteLine(tbComm.Text); else //execute default command input.WriteLine("dir \\"); input.Close(); textBox1.Text = output.ReadToEnd(); textBox1.Text += err.ReadToEnd(); }
C# Thread
.NET Framework 在 System.Threading 命名空間中定義了一些跟執行緒相關的類別。下面我們示範如何在 C# 中產生一個執行緒:
步驟一:建立一個 System.Threading.Thread 物件
建立一個 System.Threading.Thread 物件會在 .NET 環境中產生一個 managed 執行緒。Thread 類別只有一個建構式,其接受一個 ThreadStart delegate 做為參數。ThreadStart delegate 是一個回呼方法,當我們啟動該執行緒時,會呼叫該方法。
步驟二:建立回呼函式
該方法將會是我們新產生的執行緒的起始點。它可能是一個類別物件的實例方法(instance function)或是一個靜態方法。
若是該方法為實例方法,我們必須在建立 ThreadStart delegate 前,建立該類別物件;對於靜態方法而言,我們只需直接使用方法名稱來初始化 delegate。另外要注意的是,回呼方法必須以 void 來當作其回傳類型和參數;因為 ThreadStart delegate 函數的宣告為如此!
步驟三:啟動執行緒
我們可以使用 Thread 類別的 Start 方法來啟動新建立的執行緒。這個方法是非同步的方法,該方法會要求作業系統來啟動建立的執行緒。
例子
// 執行緒的回呼方法 public static void MyCallbackFunction() { while (true) { System.Console.WriteLine("Hey!, My Thread Function Running"); ……… } } public static void Main(String []args) { // 建立執行緒物件 Thread MyThread = new Thread(new ThreadStart (MyCallbackFunction)); MyThread.Start() …… }
刪除執行緒
藉由呼叫執行緒物件的 Abort 方法,我們可以刪除一個執行緒。呼叫 Abort 方法會造成目前的執行緒拋出 ThreadAbortException 例外,並結束執行。
MyThread.Abort();
暫停和恢復執行緒
我們可以用 Suspend 方法來暫停一個正在執行中的執行緒,或從另一個執行緒中使用 Resume 方法來恢復一個執行緒的執行。
MyThread.Suspend() // 暫停執行緒執行 MyThread.Resume() // 恢復執行緒執行
執行緒狀態
執行緒可能處於下列幾種狀態:
- Unstarted:執行緒已經被建立於 Common Language Runtime 中,但是還未啟動
- Running:執行緒的 Start 方法被呼叫後,即進入此狀態
- WaitSleepJoin:當呼叫執行緒的 wait、Sleep 或是 Join 方法時,會進入此狀態
- Suspended:當 Suspend 方法被呼叫時,會進入此狀態
- Stopped:執行緒終止(不論是正常終止或是 Abort)
藉由使用 Thread 的 ThreadState 屬性我們可以得知目前執行緒所處的狀態。
執行緒優先權
Thread 類別的 ThreadPriority 屬性用來設定該執行緒的優先權。可用的值包括:Lowest、BelowNormal、Normal、AboveNormal、Highest。預設值為 Normal。
Cross compile
因為從 GENIA 中下載的 geniatagger 只有 Linux 版本,所以我們必須使用 cygwin 來將它編譯成為可以在 windows 上使用的版本。
要做 cross compile 很簡單,只要在安裝 cygwin 時記得安裝 g++、gcc 以及 vim (可以不安裝)後,就可以在 cygwin 的視窗中下達 gcc/g++ 來做編譯。要注意的是,若是要將編譯好的 exe 檔在其它的電腦上執行,必須要複製 cygwin1.dll 檔。
沒有留言:
張貼留言