全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4927
推到 Plurk!
推到 Facebook!

等待Thread結束

答題得分者是:aftcast
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-11-26 23:50:08 IP:123.193.xxx.xxx 訂閱
請問一下各位
我有一個函式,其中會啟動一個Thread,希望能等待Thread Suspend後再繼續下去
但使用WaitForInputIdle及 waitforsingleobject都不能做到
請問各位高手,要如何解決,謝謝
以下是函式

{
TurnWaiting->Resume();
WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE);
//do something after TurnWaiting Suspend....
}
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-11-27 09:47:33 IP:59.115.xxx.xxx 訂閱
1需要自己先createevent,參考如下

mDoWorkFlag = ::CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
"NotifyWork" // object name
);

上面的mDoWorkFlag必需是全域的變數

2/在你呼叫TurnWaiting->Suspend( )的下面加上一條
::SetEvent(mDoWorkFlag);

3/ 使用waitforsingleobj(mDoWorkFlag,INFINITE)

4/ 在做好所有的事後加::ResetEvent(mDoWorkFlag);


寫到這裡,我突然看到你的程式碼怎怪怪的???!!

{
TurnWaiting->Resume(); //resume後你怎麼會期待它自己suspend?? 等它terminate還有可能! 或者你在等使用者自己去按某個鍵然後suspend?
WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE);
//do something after TurnWaiting Suspend....
}

我已經告訴你方法了,可是你的程式logical有些問題,自己要想清楚。

或者你把程式的流程講一下… 我實在是想不到這樣的應用方式…

疑?? 剛又看了一下你的標題,怎麼會是「等thread結束」,到底是suspend還是結束?? 若是結束,那問題非常的簡單,只要用TurnWaiting->WaitFor就搞定了
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-27 09:53:16, 註解 無‧
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-11-27 11:54:11 IP:123.193.xxx.xxx 訂閱
aftcast您好:
感謝您的回覆
我這個程式碼是一個函式,執行到某個條件的時候
需要等待使用者從form上面的button或是其它vcl做出操作
然後根據操作的內容然後運算後回傳一個值
有點類似象棋AI程式,玩家在上面移動棋子以後,電腦再做出相對應的應手
但是玩家在下決定之前,電腦也在背景思考

目前的想法是按下button的時候
把參數傳給TThread
然後順便呼叫Suspend
函式就可以繼續

不過遇到的問題就是
thread在執行的時候
函式會直接跳過他回傳一個值
造成錯誤 因為不是正確的結果

使用waitfor的話我也想過
不過會發生整個Form被凍結
然後無法讓使用者操作button的情況

再次感謝您的熱心回應
我晚點來試試這個方法

===================引 用 aftcast 文 章===================
1需要自己先createevent,參考如下

mDoWorkFlag = ::CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
"NotifyWork" // object name
);

上面的mDoWorkFlag必需是全域的變數

2/在你呼叫TurnWaiting->Suspend( )的下面加上一條
::SetEvent(mDoWorkFlag);

3/ 使用waitforsingleobj(mDoWorkFlag,INFINITE)

4/ 在做好所有的事後加::ResetEvent(mDoWorkFlag);


寫到這裡,我突然看到你的程式碼怎怪怪的???!!

{
TurnWaiting->Resume(); //resume後你怎麼會期待它自己suspend?? 等它terminate還有可能! 或者你在等使用者自己去按某個鍵然後suspend?
WaitForInputIdle((HANDLE)TurnWaiting->Handle, INFINITE);
//do something after TurnWaiting Suspend....
}

我已經告訴你方法了,可是你的程式logical有些問題,自己要想清楚。

或者你把程式的流程講一下… 我實在是想不到這樣的應用方式…

疑?? 剛又看了一下你的標題,怎麼會是「等thread結束」,到底是suspend還是結束?? 若是結束,那問題非常的簡單,只要用TurnWaiting->WaitFor就搞定了
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-11-27 12:43:15 IP:123.193.xxx.xxx 訂閱
您好:
剛剛試了您的方法
因為這是第一次寫thread程式
不知道有沒有誤用
但是還是沒有達成預期的效果
我寫了一個比較簡單的測試程式
能否請幫我看看 謝謝

以下是Button3按下以後,程式會開始等待看是Button1被按了,還是Button2


Thread的h
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
class testThread : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall testThread(bool CreateSuspended);
int Pressed;
};
//---------------------------------------------------------------------------
#endif



Thread的cpp
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall testThread::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------
__fastcall testThread::testThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
Pressed = 0;
}
//---------------------------------------------------------------------------
void __fastcall testThread::Execute()
{
//---- Place thread code here ----
while(Pressed == 0)
{
Sleep(1000); //等待到pressed變數改變
}
}
//---------------------------------------------------------------------------




Form的h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include
#include
#include
#include <Forms.hpp><br />#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TButton *Button3;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
testThread* test;
HANDLE mDoWorkFlag;
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif



Form的cpp
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
test = new testThread(true);
mDoWorkFlag = ::CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
"NotifyWork" // object name
);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
test->Resume(); //按下後程式進入等待 直到test被suspend
::SetEvent(mDoWorkFlag);
WaitForSingleObject(mDoWorkFlag,INFINITE);
::ResetEvent(mDoWorkFlag);
if (test->Pressed == 1) //suspend後,開始判斷
{
ShowMessage("Button1");
}
else if (test->Pressed ==2)
{
ShowMessage("Button2");
}
ShowMessage("out"); //失敗了,因為沒有等thread結束後才往下走
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend
test->Suspend();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
test->Pressed = 2;
test->Suspend();
}
//---------------------------------------------------------------------------
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-11-27 15:24:43 IP:59.115.xxx.xxx 訂閱

===================引 用 raistlinmiao 文 章===================
您好:
剛剛試了您的方法
因為這是第一次寫thread程式
不知道有沒有誤用
但是還是沒有達成預期的效果
我寫了一個比較簡單的測試程式
能否請幫我看看 謝謝

以下是Button3按下以後,程式會開始等待看是Button1被按了,還是Button2


Thread的h
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
class testThread : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall testThread(bool CreateSuspended);
int Pressed;

};
//---------------------------------------------------------------------------
#endif



Thread的cpp
//---------------------------------------------------------------------------
#include
#pragma hdrstop

#include "Unit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall testThread::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------
__fastcall testThread::testThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
Pressed = 0;
}
//---------------------------------------------------------------------------
void __fastcall testThread::Execute()
{
//---- Place thread code here ----
while(Pressed == 0)
{
Sleep(1000); //等待到pressed變數改變
}
}
//---------------------------------------------------------------------------




Form的h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include
#include
#include
#include <forms.hpp><br />#include "Unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
TButton *Button3;
void __fastcall FormCreate(TObject *Sender);
void __fastcall Button3Click(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
testThread* test;
HANDLE mDoWorkFlag;
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif



Form的cpp
//---------------------------------------------------------------------------</forms.hpp></stdctrls.hpp>

#include
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
test = new testThread(true);
mDoWorkFlag = ::CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // initial state is signaled //這裡改成一開始是無訊號的,即阻檔的
"NotifyWork" // object name
);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
test->Resume(); //按下後程式進入等待 直到test被suspend

WaitForSingleObject(mDoWorkFlag,INFINITE); //這裡開始一直等待直到mDoWorkFlag被通知放行
::ResetEvent(mDoWorkFlag); //這裡的意思是把事件物件又設定為阻檔的
if (test->Pressed == 1) //suspend後,開始判斷
{
ShowMessage("Button1");
}
else if (test->Pressed ==2)
{
ShowMessage("Button2");
}
ShowMessage("out"); //失敗了,因為沒有等thread結束後才往下走
Button1->Enabled = true; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend,
Button2->Enabled = true; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend
Button1->Enabled = false; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend,
Button2->Enabled = false; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節

test->Suspend();
::SetEvent(mDoWorkFlag); //將事件物件設定為有訊號的,即可通行的

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
test->Pressed = 2;
Button1->Enabled = false; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend,
Button2->Enabled = false; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節

test->Suspend();
::SetEvent(mDoWorkFlag); //將事件物件設定為有訊號的,即可通行的
}
//---------------------------------------------------------------------------
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-11-27 18:26:58 IP:123.193.xxx.xxx 訂閱
您好:
非常感謝您熱心的回答
不過我剛剛試了一下您改動的部份
發現當我按下button3的時候
整個程式就會凍結住
無法按下button1及button2

能否請您再幫我看看嗎
謝謝

我不知道怎麼上傳我的整個project
不過基本上跟您改動的一模一樣

再次感謝
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-11-27 20:56:35 IP:60.248.xxx.xxx 訂閱
嗯,我跟著你的想法去改竟忘了會有凍結的情形!!

晚點有時間再幫你想看看。

此外,初步的概念是你可能需再建立一個thread,然後把waitforsingleobject放在新thead上。事實上這個api通常是用在thead上的面的。

你可以提供一下你原來的thead裡面是要做什麼嗎? 你只寫了sleep,我想知道你大概是想做什麼…

整個程式的logical還是有點怪怪的,當然,也許是我不了解你真的用意是什麼,你只說了大概像是象棋ai的情形…
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-11-27 21:48:26 IP:123.193.xxx.xxx 訂閱
感謝您的回應

我想寫的是一個遊戲

類似象棋 電腦動一步以後 玩家再動一步

但是玩家在思考的時候 電腦也在思考

電腦動作以後會開啟一個函式

函式執行到一半

會需要玩家去移動Form上面的vcl元件

然後再根據元件的移動來產生結果

所以那函式裡面就是Sleep();來等待玩家

邏輯可能是真的怪怪的..

如果真的不行的話 目前的權宜想法

就是先條件產生時

先開啟一個函式叫醒thread

然後函式結束

等到thread執行完了

再透過sendmessage給form

然後form再去呼叫另一函式來計算結果

不過這樣寫的話 整個結構會變的怪怪的

再次感謝您熱心的指導

===================引 用 aftcast 文 章===================
嗯,我跟著你的想法去改竟忘了會有凍結的情形!!

晚點有時間再幫你想看看。

此外,初步的概念是你可能需再建立一個thread,然後把waitforsingleobject放在新thead上。事實上這個api通常是用在thead上的面的。

你可以提供一下你原來的thead裡面是要做什麼嗎? 你只寫了sleep,我想知道你大概是想做什麼…

整個程式的logical還是有點怪怪的,當然,也許是我不了解你真的用意是什麼,你只說了大概像是象棋ai的情形…
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-11-28 10:07:06 IP:59.115.xxx.xxx 訂閱
早,昨晚竟失眠,就因為想不出你這個問題的內容流程是如何的。

了解你說明了二次類似象棋的game,但詳細一點的流程圖都沒有,比如說1按button2做什麼3再如何4……

又,你說:

電腦動作以後會開啟一個函式

函式執行到一半

會需要玩家去移動Form上面的vcl元件

然後再根據元件的移動來產生結果

所以那函式裡面就是Sleep();來等待玩家


不清楚這段話是什麼意思。是開一個怎樣的函式?大概是做啥功能? 而最後一句話,裡面就是SLEEP ? 難道你那個thread裡真的就只需要執行一句話sleep?就一句?

想了很久,我自己就當你是寫象棋來看待,但發現你的寫法和象棋好像差很多。比如說
為何會需要suspend??? 這個問題是我試著回你的時候發現的,好像沒有很好的理由需要suspend一個thread後才能去做什麼事!

我本來想好要設定二個thread的結構來處理你的問題,但發現套不上你的想法… 下面是我一早試著寫給你的東西


1/ 產生一個thread_brain,它負責背景不停的"思考",它接受來自user透過元件傳來的一些參數,並進一步的變化"思路"
2/ 產生另一個thread_worker,它主要用來負責user操作元件後的後序處理,比如說更動某些元件的屬性,把一些訊息傳給thead_brain。

流程與限制:
1/ 開始的時候thread_brain就啟動,直到user按下某些元件後被suspend
2/ 開始的時候thread_worker是不啟動的,直到user按下某元件後再把它啟動
3/ 當user按下元件後……

寫到3的時候,我發現自己寫不下去,因為好像都不需要suspned之類的,且好像一個thread也可以解決你的問題


我很頭痛,我很想幫你,但似乎在沒理清你的結構時是幫不了的。可能的話請試著像我上面那樣分析流程,並寫出來。每個thead的功能,每個函式的功能,整個動作的流程方向等… 而大概的說法就不用了,我懂你大概是要寫類似象棋的東西…

注: suspend與waitforsingleobject 有一點點類似,但決決大多數不會使用suspend。若你要確定某種情形下才開始做下面的動作,那100%是用waitforsingleobjcet。這二個似乎不可能混在一起用,更進一步的說,suspend應該不需要存在而可以用waitforsingleobjcet來取代一切!! 所以我真的該了解你為何一定要suspned?? 也許你想要的不是你該用的函式。
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-28 10:21:18, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-11-28 10:47:49 IP:59.115.xxx.xxx 訂閱
寫完上一篇的一推話後,我有一點的想法,先幫你改成一個較正式的範例,是照我自己的想法做的。

但還是請你回覆我上篇的內容喔!


Thread的h
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include
//---------------------------------------------------------------------------
class testThread : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall testThread(bool CreateSuspended);
int Pressed;
void __fastcall testThread::UpdateButton();
Form1->Button1->Enabled = true; //此行與下行是我精心幫你設想的,為了防止多按幾次suspend,
Form1->Button2->Enabled = true; //因為多按一次,resume要多執行一次才會起來,這是非常細的細節
while (!Terminated) //不停的處理事情
for (int 1= 1; i <100; i ) ; //這句話是模擬你可能要事前處理的事務
if ( WaitForSingleObject(Form1->mDoWorkFlag,INFINITE)==0L) //若有通知訊息才會放行下面的程式,不然就等在這裡

if (pressed = 2) ::MessageBox(0,"Botton2 pressed","",MB_OK);
::ResetEvent(Form1->mDoWorkFlag); Synchronize(UpdateButton); //把form的button 再show 出來


void __fastcall TForm1::Button3Click(TObject *Sender)
test->Resume(); //這裡執行後會造成thread裡的一段程式開跑,哪一段? waitforsingleobject前的那一些前戲
void __fastcall TForm1::Button1Click(TObject *Sender)
test->Pressed = 1; //按下以後 更改thread裡的變數 然後suspend
此時thead的wait那段就會自動開跑了…

}
void __fastcall TForm1::Button2Click(TObject *Sender)
test->Pressed = 2;
此時thead的wait那段就會自動開跑了…

}
//---------------------------------------------------------------------------

我沒實際在bcb上跑,我是用我的腦子跑著改的,故可能會有語法或是錯別字,compile有誤時請自行修改。但架構就是這樣!
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-11-28 10:49:32, 註解 無‧
aftcast 重新編輯於 2008-11-28 10:51:19, 註解 無‧
aftcast 重新編輯於 2008-11-28 10:54:58, 註解 無‧
raistlinmiao
一般會員


發表:17
回覆:20
積分:12
註冊:2004-10-22

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-11-28 13:49:45 IP:123.193.xxx.xxx 訂閱
您好:
感謝您這麼費心在我的問題上面
原本以為整個程式的架構是不用寫出來來讓問題變更複雜
不過經過您這麼一說
我發現有可能是我的邏輯上的問題
讓整個流程陷入了死路
我說一下我整個程式想做的東西請您參考一下
其實就是類似象棋的棋類小遊戲
但是要分成可以人類跟人類玩
人類跟ai玩
還有ai跟ai
而且隨時可以換手(電腦接手人類這邊 或人類接手電腦)
目前的做法是先在Form下面宣告一個Game class
然後Game class下面有兩個player class
然後ai及human class繼承player class
所以當換手的時候我就把指標換人
遊戲可以繼續進行

目前game class的簡化流程是

currentgame = player1->nextmove();
currentgame = player2->nextmove();
...
想完然後回傳
問題是不論是人類或是電腦在思考的時候
不會馬上回傳答案
所以必需等待
也就是sleep();
現在的做法就是換人類的時候
先sleep();
等待盤面被移動的時候
把盤面轉換成參數
然後傳給player
然後player再回傳給game
但是一sleep整個畫面是被凍結的
所以人類不能移動盤面
所以想開個thread
接下來就有上面的問題

不過現在來看
好像就是這個想法讓整個流程有誤
如果只是簡單的下棋程式
那一般的做法是為何呢?

真的非常感謝您這麼熱心
<(_ _)>
系統時間:2024-04-25 20:09:53
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!