none
Thread突然消失的問題 RRS feed

  • 問題

  • 自己用ASP.NET寫了一個棒球遊戲, 並用Thread來計算比賽過程, 只要有比賽再進行Thread就不會結束.
    但是奇怪的是, 當網站架在自己家裡的電腦運行的時候都一切正常, 可是把網站搬出去, 不管是shared hosting還是VPS, 都會發生Thread莫名其妙消失的情況. 用log紀錄也是一無所獲, 完全沒有任何錯誤訊息, Thread就是憑空消失了??

    由於第一次只用Thread, 在網上查了很多之後寫出了以下的程式碼:

        public static void Start_Heart_Beat()
        {
            if (HEART_BEAT == false)
            {
                try
                {
                    Thread heart_beat = new Thread(new ThreadStart(Heart_Beat));
                    heart_beat.IsBackground = true;

                    heart_beat.Start();
                    HEART_BEAT = true;

                    ConstClass.Error_Log("HEART_BEAT Started!");

                }
                catch (Exception e)
                {
                    ConstClass.Error_Log(e);
                }
            }

        }

        private static void Heart_Beat()
        {
            while (GAME_LIST.Count > 0)
            {
                GameInfo game_info = null;
                int game_playing = 0;

                try
                {
                    for (int i = 0; i < GAME_LIST.Count; i++)
                    {
                        game_info = (GameInfo)GAME_LIST[i];

                        if (game_info == null || game_info.Live_Message.Count == 0) continue;

                        game_playing++;
                        Game_Process(game_info);
                    }

                    if (game_playing == 0)
                    {
                        ConstClass.Error_Log("game_playing == 0 ==> break;");
                        break;
                    }

                    ConstClass.Error_Log("Thread " + Thread.GetDomainID() + " (" + game_playing + " games are playing)");
                    Thread.Sleep(REFRESH_TIME);
                }
                catch (Exception e)
                {
                    ConstClass.Error_Log(e);
                    ConstClass.Error_Log("Error in Game " + GAME_LIST.IndexOf(game_info) + " of " + GAME_LIST.Count + " (第" + game_info.Inning + "局)");
                    //break;
                }
            }

            ConstClass.Error_Log("Heart_Beat() has ended ==> GAME_LIST.Count is " + GAME_LIST.Count + "");
            GAME_LIST.Clear();
            HEART_BEAT = false;

        }
     
    只要執行一段時間後(有時候可以維持幾個小時, 有時候幾分鐘就掛了)就收到以下的錯誤訊息:
    Source        : mscorlib
    Method        : SleepInternal
    Error         : Thread was being aborted.
    Stack Trace   : at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
       at System.Threading.Thread.Sleep(Int32 millisecondsTimeout)
       at GameClass.Heart_Beat() in c:\Inetpub\wwwroot\CPBLOnline\App_Code\GameClass.cs:line 130


    這個問題困擾了我很久, 也查過是不是VPS有限制記憶體使用量的原因, 不過每次出錯的時候都沒有收到記憶體使用超標的警告..
    所以到現在還是滿頭霧水完全不知道問題出在哪裡..

    不知道有沒有高手可以解答這個問題?
    感謝!

    2009年6月18日 下午 03:49

解答

  • 你的需求沒辦法這麼容易達到
    因為網頁的生命週期建構在Client的 Request,所以如果你把Thread的instance建立在asp.net程式中,那就會有消失的問題.

    提供做法
    1.將thread建立在Application Start上,用Application變數來存取.
    2.將thread建立static變數上.
    以上是較簡單的做法,但可能會衍生出一些問題.
    比較好的做法是將這類的Thread獨立成windows service application再透過remoting來與asp.net溝通會是比較好的方式.

    • 已標示為解答 Szuwei 2009年6月19日 上午 01:51
    • 已取消標示為解答 Szuwei 2009年6月19日 上午 01:51
    • 已標示為解答 Szuwei 2009年6月19日 下午 04:40
    2009年6月19日 上午 12:14
  • 當網頁虛擬應用程式最後要求結束後,預設 20 分鐘內沒人存取,所有該虛擬應用程式產生的執行緒或資源都會被釋放。

    沒設 static 的話,會跟隨要求,預設 90 秒內結束,設 static 的話,跟隨虛擬應用程式,20 分鐘內沒人存取結束,兩種方式都會結束,所以才會不應該寫在網頁內有持續的執行緒再跑。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    • 已標示為解答 Szuwei 2009年6月19日 下午 04:40
    2009年6月19日 下午 12:56

所有回覆

  • 網頁程式為啥要開一個 Thread 來跑?網頁本身是 off-line 的架構,請確認你的設計。
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    2009年6月18日 下午 04:46
  • 因為跑比賽Thread的同時, 玩家還可以做一些其他的動作, main Thread 還要處理玩家發來的request.
    不好意思, 可能是我沒解釋清楚, 這個程式是在一個後台的class裡, 只要比賽開始之後, 不管玩家網頁開不開著都要繼續跑到比賽結束為止.
    2009年6月18日 下午 05:05
  • 你的需求沒辦法這麼容易達到
    因為網頁的生命週期建構在Client的 Request,所以如果你把Thread的instance建立在asp.net程式中,那就會有消失的問題.

    提供做法
    1.將thread建立在Application Start上,用Application變數來存取.
    2.將thread建立static變數上.
    以上是較簡單的做法,但可能會衍生出一些問題.
    比較好的做法是將這類的Thread獨立成windows service application再透過remoting來與asp.net溝通會是比較好的方式.

    • 已標示為解答 Szuwei 2009年6月19日 上午 01:51
    • 已取消標示為解答 Szuwei 2009年6月19日 上午 01:51
    • 已標示為解答 Szuwei 2009年6月19日 下午 04:40
    2009年6月19日 上午 12:14
  • 不過當我在自己家的Server運行的時候好像完全都正常呢,這是甚麼原因呢?
    2009年6月19日 上午 01:53
  • 那是錯覺...
    只要是web application都有這類問題存在.

    而且我有個疑問
    你使用ASP.Net來設計,但你的程式是如何做到各Client是互通同一個thread來計算分數?



    2009年6月19日 上午 02:29
  • 我就是在ASP.NET的project裡開了一個class專門做比賽的計算,把所有比賽的資料都存在那個class裡面,然後所有用戶都從那個class裡面去讀取資料。
    一開始跑得都很順,搬出去之後突然間就出現這個thread無故消失的問題,因為在自己家跑的時候都跑不出這個問題,所以實在無從查起。
    2009年6月19日 上午 02:44
  • thread 消失的問題一定是web特性造成.

    另外寫multithread用class共用資料不是個好方式,如果資料同步未處理好,很容易發生資料存取覆蓋的問題,而且這種問題非常難debug.

    2009年6月19日 上午 02:53
  • 還想請問一下, 您提供的解決方法裡面, 將thread設成static的就能解決這個問題嗎?

    像這樣嗎?

        private static Thread heart_beat;

    2009年6月19日 上午 03:13
  • 因你沒有把所有程式碼都列出,無法正確的給你答案
    你應該是要將處理計算分述的那個Class所建立的instance儲存在Application變數之中或static變數.

    2009年6月19日 上午 08:54
  • 當網頁虛擬應用程式最後要求結束後,預設 20 分鐘內沒人存取,所有該虛擬應用程式產生的執行緒或資源都會被釋放。

    沒設 static 的話,會跟隨要求,預設 90 秒內結束,設 static 的話,跟隨虛擬應用程式,20 分鐘內沒人存取結束,兩種方式都會結束,所以才會不應該寫在網頁內有持續的執行緒再跑。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    • 已標示為解答 Szuwei 2009年6月19日 下午 04:40
    2009年6月19日 下午 12:56