2007年6月23日

Windows Form vs Multithread

最近試著用C#練習寫BT(bluetooth)搜尋程式,為了讓搜尋時視窗不要因為搜尋時而導致視窗無法移動,因此,最簡單的方式,就是在增加一個thread來處理搜尋的動作,等處理完後再將結果顯示在ListBox上:

##CONTINUE##

public void Search_Click(object sender, EventArgs e)

{
this.listBox_devices.Items.Clear();
this.Text = "Search Bluetooth Device...";
this.search_thread = new Thread(new ThreadStart(search));
search_thread.Start();
}

private void search()
{
this.listBox_devices.Items.Clear();

InTheHand.Net.Sockets.BluetoothClient bc = new InTheHand.Net.Sockets.BluetoothClient();

InTheHand.Net.Sockets.BluetoothDeviceInfo[] array = bc.DiscoverDevices();

for (int i = 0; i <>

this.address_array[i] = array[i].DeviceAddress;
this.listBox_devices.Items.Add(array[i].DeviceName);

}

}

上面程式在按下Search按鈕後將會啟動Search thread處理搜尋的功能,搜尋完後會將蒐尋到的BT Devices的名稱儲存下來並顯示在ListBox中,看起來似乎沒甚麼問題,但程式在按下Search按鈕後程式就當掉了!

原來問題在於,只有建立Windows Form的thread才能存取、修改Form或控制項的內容,因為.NET的控制項在設計時是執行緒相依(thread affnity),只有在建立該Form或控制項的執行緒才能安全地存取其屬性。



當控制項的狀態改變時,系統會把它轉換成視窗訊息,放到訊息佇列中(Message Queue),再由程式處理!

不過,將訊息放入訊息佇列(Message Queue)的方式分為兩種,一種為SendMessage(),一個則為PostMessage()。前者為呼叫者會停住直到訊息被處理為止;而後者呼叫端則是將訊息放置訊息佇列後即立刻返回。

而在.NET裡,所有Form或是控制項的屬性變更,皆由SendMessage()送出訊息!

因此,在上面的程式中,當主執行緒等待搜尋執行緒完成,而搜尋執行緒因為嚐試更新控制項,因此呼叫了SendMessage(),而SendMessage()會因此使搜尋執行緒停住,因為它必須停主執行緒將SendMessage()送出的訊息處理,而主執行緒也在等待搜尋執行緒執行完畢,因此變成互相等待的情形,程式因此當掉了!


2007年6月9日

iPhone is coming~~





2007年6月8日

C# : Delegate(委派)

用來宣告委派 (Delegate)。委派是一種參考型別,它參考型別的 Shared 方法或物件的執行個體方法 (Instance Method)。任何具有相符參數型別和傳回型別的程序都可用來建立這個委派類別的執行個體。接著可透過委派執行個體來叫用程序。
##CONTINUE##
Delegate 陳述式定義委派類別的參數型別和傳回型別。任何具有相符參數型別和傳回型別的程序都可用來建立這個委派類別的執行個體。接著可透過委派執行個體來叫用程序,方式是呼叫委派的 Invoke 方法。

~MSDN

Delegate(委派)大致類似 C++ 的函式指標(Function Pointer),函數指標的致命缺點是:無法對參數 (parameter) 和返回值 (return value) 的型態進行檢查,因為函數已經退化成指標,指標是不帶有這些型態資訊的。少了型態檢查,當參數或返回值不一致時,會造成嚴重的錯誤。編譯器和虛擬機器 (VM) 並不會幫我們找出函數指標這樣的致命錯誤。所以,許多新的程式語言不支援函數指標,而改用其他方式。

至於為什麼會需要function pointer、delegate機制呢?簡單的想法:『為什麼我們不能將function也如同變數一樣傳進另外一個function呢?』,C語言的解決方式是,利用pointer指向該function,將該pointer傳入另外一個function,只要將該pointer dereference後,就如同存取原function一樣。C#解決的方式是,將function包成delegate object,傳入另外一個function。

參考" Function Pointer、Delegate和Function Object (初級) (C/C++) (OO C++) (Template C++) (C#)"

2007年6月4日

Visual Studio 2005試用

##CONTINUE##
最近重新安裝Visual Studio 2005再試用一下,之前使用的時候,總是無法順利的部署到機器上,這次到網路論壇上找了一下,發現原來之前安裝的順序錯了,正確的安裝順序應該是:
1. 安裝Visual Studio 2005
2. 安裝裝置的SDK
3. 在Visual studio 2005的選單上,選取"工具\連接到裝置",選取要連結的裝置即可,例如SNAXXXX

接下來就可以開啟新的專案來開發新的Ap了,試用C#寫了一個簡單的Ap確實可以在760上Run,不過第一次部署時,花了不少的時間安裝檔案,還目前還不清楚需要哪些檔案才能執行?