2009年2月27日

與 UserControl 動態產生的控制項互動

就在前幾天在瀏覽各大部落格的文章時,
看到 Johnny 大大寫的這篇 [UserControl] 網頁生命週期與取不到 UserControl 資料的問題
原本坎尼已經快睡著了,看到結論的地方突然醒了!!!!!

還記得坎尼之前寫了一篇 如何設定UserControl中動態產生的控制項初始值
坎尼當時的著眼點在 Page_Load
一直都忘了 Page_Init... Page_Init... Page_Init...
於是坎尼又做了下面的測試

新增一個 UserControl ,裡面加入一個 DropDownList
並在 Page_Init 事件動態增加項目


新增一個 WebForm,並將剛剛的 UserControl 引用到頁面上

在剛剛的WebForm 的 Page_Load 事件
加入指定的 SelectedIndex

執行畫面,並未出現 "未設為執行個體" 的 Exception
登登~~成功~~


所以坎尼之前那次的研究還真的是繞了不少路啊 (汗)

坎尼記得坎尼的朋友小馬王有寫過 ASP.NET生命週期的文章
有興趣的人可以看看

最近加入了圖片放大的Script
使用上有什麼意見可以回覆這篇文章或寄信
(Tim你就別來亂了...說什麼很噁心)

2009年2月23日

解決 vs 2005 在 IE8 上不能開啟 debug 模式

其實這個問題坎尼在 IE8 beta 剛出來的時候就發現了
不過由於很快就找到解決方式,所以坎尼認為應該只是個案吧....

先講一下坎尼的開發環境
win xp sp3
vs 2005 sp1
vs 2008 sp1
ie8 beta2

發生的情境...
用 vs2005 開發的網站專案按下 F5 時
IE顯示頁面之後, Debug 模式就自己關掉了
此時 IE及頁面仍會留著,但無法用小紅點 Debug
(等同在專案的頁面上按 View with Browser)

坎尼剛剛上網找了一下...發現了這位 苦主
底下也有人提供了解決方案

不過不想改登錄碼的人,可以試試下列坎尼發現的方法
  1. 關閉所有IE視窗

  2. 打開vs2008,並開啟一個Web專案

  3. 用vs2008進入debug模式 (按下F5)

  4. 接著就能用 vs2005 來 debug 囉!!!
2009/03/09 修正
坎尼後來發現,其實和用 vs 2008 做 debug 的動作沒啥關係
只要把目前所有開啟的 IE8 視窗關掉
再執行 vs 2005 的 debug 模式即可
不過為什麼會這樣,坎尼目前還不曉得 XDDD

vs2008只要執行一次debug即可

坎尼在猜,vs2008應該只是要讓debugger導到正確的process
不過這個方法只要電腦重開就要重新做一次

對了 本篇沒圖 XDDD

2009年2月22日

無法預測、無法控制的 ASP.NET multi-thread 機制

所謂的 thread 是甚麼相信大家都知道,多少也在學生時代寫過一兩個多執行緒的作業。
在 .NET 的世界裡面,無論是Web Apps or Windows Apps,在 runtime 時期都是在 CLR 上運作,而 CLR 所看到的都是在 AppDomain 中執行的 thread,
Web/Windows Apps 的分別只是在於 CLR 載入的 aassembly 不同罷了。

從上上週末開始,我們 Team 就開始設法利用 TLS 來解決舊元件造成的 MSDTC 問題,
在想像中這個 solution 可以同時滿足 Web Apps & Windows Apps ,
沒想到就此一頭栽進了深不見底的 ASP.NET multi-thread 地獄。
(到現在還是處於一頭霧水的狀態 Orz)


經過5個系統的實測(4個是各部門的系統,另一個是自己寫的超小型 demo 網站),
我們發現「ASP.NET 在某些不明條件下,會以 multi-thread 的方式來處理 Request」,
也就是「custom httpModule 與 page 的 code-behind 是以不同的 Thread 在運作」,
這與我們想像中的「ASP.NET 對一個 Request 從頭到尾都是以單一 Thread 來處理」的假設完全不同,而這種現象使得 TLS Solution 呈現完全報廢的狀態,為甚麼呢?

在 What’s ThreadLocalStorage 這篇文章中所附的範例程式中,我是在一個自己撰寫的 custom httpModule 中去處理 TLS 中的資料,若 ASP.NET 的行為一如預期的是以單一 Thread 來處理 Request,那麼在page 的 code-behind 程式 中便可順利取得在 custom httpModule 中存入 TLS 的資料(connection & transaction 物件),也就可以執行 local transactions 而不需勞師動眾的啟動 distributed transaction (MSDTC) 了。

但是當 ASP.NET 以新的 Thread (#2) 來處理 page 的 code-behind 程式時,Thread #2 是無法取得 custom httpModule (Thread #1) 的 TLS 中的 connection & trnasaction 物件的(不然怎麼叫 ThreadLocalStorage 呢?),因此在 code-behind 的程式中要 access DB 時便會出現 NullReferenceException!

奇怪的是,在拿來實測的系統中完全沒有撰寫 multi-thread 的程式(e.g., Thread.Start()),因此目前推測 multi-thread 現象是 ASP.NET 內部所做的 (Performance) Optimization 所產生的結果,是我們的程式無法(起碼很難)控制的。

在5個實測過的系統中,出現以下的 multi-thread 現象:
(System E 是自己寫的超小型 demo 網站)
  • 有插入 custom httpModule:
    • System A: httpModule 屬於 Thread #1,page 屬於 Thread #2
    • System B: httpModule 屬於 Thread #1 & #2,page 屬於 Thread #3 ~ #n
    • System C: httpModule 與 page 屬於 Thread #1 (使用單一 Thread!)
    • System D: httpModule 屬於 Thread #1,page 屬於 Thread #2
    • System E: httpModule 與 page 屬於 Thread #1 (使用單一 Thread!)
  • 不插入 custom httpModule (也就是一般寫網站的狀況):
    • System A: page 屬於 Thread #1 ~ #n
    • System B: page 屬於 Thread #1 (使用單一 Thread!)
    • System C: 沒有測到
    • System D: page 屬於 Thread #1 (使用單一 Thread!)
    • System E: httpModule 與 page 屬於 Thread #1 (使用單一 Thread!)
根據上述現象,目前推測與 ASP.NET multi-thread 機制無關的因素包括:
  • .NET Framework 版本 (1.1/2.0/3.5)
  • IIS 版本 (6.0/7.0)
  • 是否(混合)使用 MasterPage、UserControl、CustomControl
  • Page 是否繼承自己包的 BasePage
  • 頁面是否有用 frame 切割
而推測可能有關的因素包括:
  • 某種程式寫法會造成 ASP.NET 內部自動改以 multi-thread 來執行
    • 在 page 中以 js 另開視窗(做一些事情)之後再關閉的程式寫法
    • 在自己寫的超小型 demo 網站中,MasterPage、BasePage、UserControl 中的 Init / OnLoad 事件中的程式碼都是空的,不會啟動 multi-thread
  • 註冊 custom httpModule (不註冊的話,使用單一 Thread 的機率高很多)
  • 第一次 Request 與 (Ctrl+) F5 Refresh 會造成不同的效果 (不同數量的 Thread)
雖然目前還是不清楚 ASP.NET 啟動 multi-thread 機制的條件為何,但已經很明顯得到一個「TLS 此路不通」的結論,目前也沒找到比較深入的官方 reference(不過倒是曾經聽過在 ASP.NET 中最好不要自己寫 multi-thread 的程式的說法),因此這個有趣的謎只能等有空再研究囉~~

那麼要如何觀測系統是否有啟動 multi-thread 呢?以下是觀測的步驟,有興趣的人可以拿自己的系統試試看:
  1. 進入 Visual Studio 的 Debug Mode。或者先以 IIS/ASP.NET Development Server (lightweight 的那個)瀏覽到目標頁面後,將 Visual Studio 附加至該網頁的處理序上進行 debug。
  2. 在該 aspx 以及 BasePage、MasterPage、UserControl 等檔案的 code-behind 程式中的 Init / OnLoad 事件上設定中斷點。
  3. 觀察執行過程中「System.Threading.Thread.CurrentThread.ManagedThreadId」的值。

2009年2月21日

快速製作大量資料的資料表

碎碎念改了新版面囉
大家感覺這樣的配色如何呢?

這次要來講一個謎樣的 SQL 語法:Insert Into Table1 Select * From Table2
意思是:從 Table2取出資料後,通通塞進Table1
不過有個限制就是:兩邊欄位數量、順位、類型必須相符

好了,坎尼利用了這個特性來講如何快速的製作測試大量資料表

首先,先新增一個資料表
範例裡只有兩個欄位,且 oid 的類型是 identity

在 Table 裡加入一筆資料

接著打開指令輸入視窗
不過要注意的是,坎尼將 oid 設 identity
若是強制 Insert 到 identity 欄位,Sql Server 只會說:No, you can't.

所以指令會改成下圖中第二句
可以看到坎尼用的偷吃步就是:目的及來源的資料表為同一個

由於一開始只有1筆,所以畫面上只會 Insert 一筆
「一筆有什麼好了不起的?」也許Tim會這麼講
不過當坎尼按了十數次的執行語法後

可以發現,資料已經成長到十數萬筆
原因就是:由於是同一資料表,所以每做一次就成長一倍
換言之,也就是2的N次方

以這種速度按下去,再按個幾次就會有千萬筆的資料了!!!!

可是當資料成長的愈快,每次執行的速度也就愈久
所以坎尼又改了一下語法 (如下圖)

一次只取 5000 速度只有快!!! 天下武功,唯快不破
「如果要三千萬的資料,啊你是要我按到手斷掉啊」Tim又開口了
『孩子,請照顧好自己的身體健康,寫個for迴圈來跑就好』

最後來看一下前面做了那些動作的成果

See? 坎尼只是邊看電視邊按執行鍵,資料輕輕鬆鬆的成長到十萬筆 XDD

要是需要大量的資料來測試自己系統執行效率
就可以試試坎尼這個方法 :p
坎尼當年就被要求要一千萬筆資料來做壓力測試 orz

備註:
這個語法坎尼只在 MS Sql Server 裡用過
不過 Google 大神好像講說其他資料庫也能這麼做
這點坎尼目前的機器上沒法驗證,有需求的人就試試看吧 :D

2009年2月15日

趁年輕的時候多啃一些硬梆梆的書

這是今年新老闆特別強調要我們做的事情,認真的讀一本經典的大頭書,
搞不好晚上看一看不小心就會因為過 high 看到凌晨 =.=

Hardcore 的新老闆列出以下幾本經典好書:
(因為都沒讀過,所以不寫甚麼評論了 … 網路上評論超多)
  • Structure an Interpretation of Computer Programs(SICP)
    (據說超難,看起來會覺得很痛苦)
  • How to Design Programs(HtDP)
    (跟 SICP 差不多,但稍微簡單一點。有辦法看完 SICP 的話這本可以用翻的)
  • Patterns of Enterprise Application Architecture(P of EAA)
    (聽說比較接近 Business,彙整了很多經過實務考驗的經典案例)
我應該會挑 P of EAA 來讀吧,這本書應該比較介於 textbook 和一般應用的書中間,
一下子挑太難的書也不太好,雖然 SICP 和 HtDP 表面上看起來還蠻好玩的…
其他還有幾本據說也是很厲害的書:

2009年2月11日

10 Harsh Truths About Corporate Websites

See Smashing Magazine.

我只能說這篇真是太好看了,Web Strategy 阿 ~~~~~
前面幾點完全就有第一手親自體驗的感覺 XD

Google Spreadsheet 裡用規則運算式

最近因為工作關係,遇到要用 Google Form 及 Google Sheet 所以研究了 Google Sheet 裡的一些 function 怎麼用 首先,分享一下如何在 Google Sheet 裡用規則運算 :D