none
重新設定為什麼會在執行一次? RRS feed

  • 問題

  • 請教各位前輩~我寫了一個能讓程式馬上重新定義時間的程式

    但是不解為什麼用setTime重新設定時間時後會先執行一次才改變時間呢?

    是我在哪裡多new一次還是無意中多執行了一次呢?

    我分成2個部分
    1.會顯示內容showTime且接受setTime的設定時間
    2用於設定時間的視窗程式

    以下為showTime的程式碼

    using System.Timers;
    using setTime;
    namespace showTime
    {
        public class Program
        {
            public static Program P;
            private static Thread showThread;
            private static System.Timers.Timer showTime;       
            private static int reTime = 5;
            private static setTime.Form1 set;
            private static showTime.Program showT;
            static void Main(string[] args)
            {
                P = new Program();
                set = new setTime.Form1();
                showT = new showTime.Program();
                showTime = new System.Timers.Timer();
                showTime.AutoReset = false;
                showTime.Interval = 5000;
                showTime.Enabled = true;
                showTime.Elapsed += new ElapsedEventHandler(showTimedEvent);
                set.ShowDialog();
                set.TimeChange(showT);
                Console.Read();
            }

            private static void showTimedEvent(object source, ElapsedEventArgs e)
            {
                showThread = new Thread(new ThreadStart(P.show));
                showThread.Start();

                showTime.Interval = reTime * 1000;
                showTime.Enabled = true;
                showTime.Start();
            }

            public void show()  //執行緒內容
            {
                Console.WriteLine("show...");
            }

            public void reSet(string time)  //重新設定時間
            {
                showTime.Stop();
                reTime = Convert.ToInt32(time);
                showTime.Interval = Convert.ToInt32(time);
                showTime.Enabled = true;
                showTime.Start();
            }
        }
    }


    以下為setTime的程式碼(視窗內有一輸入用的textBox 和按鈕)
    using showTime;
    namespace setTime
    {
        public partial class Form1 : Form
        {
            public static showTime.Program sTime = new showTime.Program();

            public Form1()
            {
                InitializeComponent();
            }

            public void TimeChange(showTime.Program sTime1)
            {
                sTime = sTime1;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                sTime.reSet(textBox1.Text);
            }
        }
    }

    2009年8月20日 上午 06:53

解答

  • 我不知為什麼大家喜歡用static 去做?
    static 有幾個地方我不太清楚.
    但有幾點我是認為不合適的的地方.
    1.static 的記憶體是配置在堆疊裡.就算你這個值現在已不使用.GC還是不會去回收.所以你主程式有很多設定參數時.我喜歡東西用時在new.不用時Dispose.
    2.在傳參數時By Value.By Reference 結果是不一樣的.我們知道大學聯考或國家特考喜歡考這種題目.有時這種題目很難解.而以目前的程式.你又Class變數.又是實例變數.值在傳,位置在配置.我真的無法預知值是否正確.

    2009年8月20日 上午 09:34
  • 程式有點亂,這種類似有多工作用的程式程式架構上要比較嚴謹些,不然很難Debug
    程式應該把責任分開
    Timer執行應該是一個class,設定的form也是一個class.兩者之間應該互不認識,切開相依性,這樣再做debug時才能很容易的找出問題點出在哪.


    參考下面的Code

    //Main.cs
    class Program { static TimeRuner runer; static void Main(string[] args) { runer = new TimeRuner(1000); runer.Start(); SetTimeForm form = new SetTimeForm(); form.IntervalChanged += new OnIntervalChangedEventHandler(form_IntervalChanged); form.ShowDialog(); Console.Read(); runer.Stop(); } static void form_IntervalChanged(int interval) { runer.Reset(interval); } }
    //TimerRuner.cs
    class TimeRuner { private System.Timers.Timer _timer; public TimeRuner(int interval) { this._timer = new System.Timers.Timer(); this._timer.Interval = interval; this._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed); } void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Console.WriteLine("Elapsed"); } public void Start() { this._timer.Start(); } public void Stop() { this._timer.Stop(); } public void Reset(int interval) { this._timer.Stop(); this._timer.Interval = interval; this._timer.Start(); } }
    //SetTimerForm.cs
    public delegate void OnIntervalChangedEventHandler(int interval); public partial class SetTimeForm : Form { public event OnIntervalChangedEventHandler IntervalChanged; public SetTimeForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int interval = int.Parse(textBox1.Text); if (IntervalChanged != null) { IntervalChanged(interval); } } }
    2009年8月20日 上午 10:13
  • 你誤會Static的意思了,Static不是不能使用而是非必要不要亂用.
    你看一下上面我PO的Sample Code與好說的有些地方不一樣.
    其實在這個SampleCode內還是可以把static TimeRuner runer這段用其他方式變為區域變數.但因為此程式並不複雜我並未這麼做.
    如果你仔細了解我上面PO的Sample Code你會發現TimeRuner與SetTimerForm互相無任何關係,這代表不論修改TimeRuner或SetTimerForm的內部運作兩者因沒有相關性所以不需要考慮對方的問題.
    但在你的程式中,所有的東西全都混雜再一起,Timer,Form與主程式,所以當你修改任何一方時就有可能會影響到其他部分,這個問題在單工情況可能很好處理,但若在多工程式下會很難Debug,因為有時候無法模擬出發生問題的狀態.
    這也是很多人從單工到多工環境後寫不出程式的原因,多工情況下如果沒有仔細思考程式的架構當程式越堆越大時會發現有修不完的Bug.

    2009年8月21日 上午 05:13
  • 我只是隨便寫一寫而已.
    我沒去特別分析你的問題.
    我寫這個範本只是解釋怎麼去寫將偶的程式.
    你用Static 你還是去把MSDN 的指引看完.
    在Windows Form  很少範本會用 Static.但很多人用Sataic 去做全域變數,讓其他的表單容易存取.這個我認為是錯的.
    Static 有很多特性.
    1.初始化時間,在Class變數跟實例變數是不同的.今天比方說,我有一支程式,裡面有三萬個表單.我不知使用者使用哪幾支表單,哪幾項功能.我用靜態的一次就配三萬表單.那不就一開始就掛了.你用實例方式.要的時候在new 在配置.做完後GC就回收.
    2.傳值時是傳參數,傳數值,不是傳表單.一支程式我要設三萬個變數.我是配置三萬個數值的值.要設這個值是new 相關的Form去做處理.處理完保留數值.Form要Dispose掉.
    3.多功,你配個靜態值.每一隻多功的程序在跑.去取該變數值.這多程序改變這個靜態值.而這個靜態值會去影響別支正在跑的值.這個你去更新實例變數是不同的.

    2009年8月21日 上午 05:47

所有回覆

  • Hi,

    set.ShowDialog();
    set.TimeChange(showT);
    試試兩句顛倒呢?!

    http://www.dotblogs.com.tw/larrynung/
    2009年8月20日 上午 07:30
  • 也是會耶,按下按鈕就會先顯示一次才等待新的時間執行
    2009年8月20日 上午 08:14
  • 我知道你要做什麼,但我不知道你在寫什麼?應該是非常簡單的程式,但你的應該不會正確.你的邏輯也不會正確.
    我看到幾個問題.
    1.static 用太多.這種程式應該不用 static.static 沒弄通,用這麼多會有問題.
    2.主程式,主表單,設定類別.這三個切得不清楚,花碌碌的.流程搞不懂怎麼跑.通常這種是單向在跑,單向參照的 Program->Form->Set.流程也是 Program 傳到  Form 傳到 SetClass,然後結果回傳.而不是我寫到哪,反正結果出來就好了.這樣如果表單很多.設定參數很多的話.你根本糾在一起.
    3.這個是小問題.Method Name 用大寫.

    2009年8月20日 上午 08:30
  • Hi,

    若要找尋多NEW的地方我是有看到
        public partial class Form1 : Form
        {
            public static showTime.Program sTime = new showTime.Program();

    但是看起來應該不會造成你的問題
    可能自己Debug Run看一下程式運行的流程會比較容易找到

    http://www.dotblogs.com.tw/larrynung/
    2009年8月20日 上午 08:45
  • 我不知為什麼大家喜歡用static 去做?
    static 有幾個地方我不太清楚.
    但有幾點我是認為不合適的的地方.
    1.static 的記憶體是配置在堆疊裡.就算你這個值現在已不使用.GC還是不會去回收.所以你主程式有很多設定參數時.我喜歡東西用時在new.不用時Dispose.
    2.在傳參數時By Value.By Reference 結果是不一樣的.我們知道大學聯考或國家特考喜歡考這種題目.有時這種題目很難解.而以目前的程式.你又Class變數.又是實例變數.值在傳,位置在配置.我真的無法預知值是否正確.

    2009年8月20日 上午 09:34
  • using System.Timers;
    using setTime;
    namespace showTime
    {
        public class Program
        {
            private System.Timers.Timer showTime;       
            private int reTime = 5;
            private setTime.Form1 set;
            static void Main(string[] args)
            {
                set=new Form1();
                showTime = new System.Timers.Timer();
                showTime.AutoReset = false;
                showTime.Interval = 5000;
                showTime.Enabled = true;
                showTime.Elapsed += new ElapsedEventHandler(set.TimeEventHandle);
                set.SetTimeEvent+=new EventHandler<int>(this.reSet);
                set.ShowDialog();
                Console.Read();
            }

            public void show()  //執行緒內容
            {
                Console.WriteLine("show...");
            }

            public void reSet(object sender,int time)  //重新設定時間
            {
                showTime.Stop();
                showTime.Interval = time;
                showTime.Enabled = true;
                showTime.Start();
            }
        }
    }


    以下為setTime的程式碼(視窗內有一輸入用的textBox 和按鈕)
    using showTime;
    namespace setTime
    {
        public partial class Form1 : Form
        {
            private Thread showThread;
            public EventHandle<int> SetTimeEvent;

            public Form1()
            {
                InitializeComponent();
            }

             private void TimeEventHandle(object source, ElapsedEventArgs e)
            {
                showThread = new Thread(new ThreadStart(P.show));
                showThread.Start();

                showTime.Interval = reTime * 1000;
                showTime.Enabled = true;
                showTime.Start();
            }
           
            private void button1_Click(object sender, EventArgs e)
            {
                if(SetTimeEvent!=null)
                   SetTimeEvent(this,Convert.ToInt32(textBox1.Text));
            }
        }
    }

    2009年8月20日 上午 09:51
  • 程式有點亂,這種類似有多工作用的程式程式架構上要比較嚴謹些,不然很難Debug
    程式應該把責任分開
    Timer執行應該是一個class,設定的form也是一個class.兩者之間應該互不認識,切開相依性,這樣再做debug時才能很容易的找出問題點出在哪.


    參考下面的Code

    //Main.cs
    class Program { static TimeRuner runer; static void Main(string[] args) { runer = new TimeRuner(1000); runer.Start(); SetTimeForm form = new SetTimeForm(); form.IntervalChanged += new OnIntervalChangedEventHandler(form_IntervalChanged); form.ShowDialog(); Console.Read(); runer.Stop(); } static void form_IntervalChanged(int interval) { runer.Reset(interval); } }
    //TimerRuner.cs
    class TimeRuner { private System.Timers.Timer _timer; public TimeRuner(int interval) { this._timer = new System.Timers.Timer(); this._timer.Interval = interval; this._timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed); } void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Console.WriteLine("Elapsed"); } public void Start() { this._timer.Start(); } public void Stop() { this._timer.Stop(); } public void Reset(int interval) { this._timer.Stop(); this._timer.Interval = interval; this._timer.Start(); } }
    //SetTimerForm.cs
    public delegate void OnIntervalChangedEventHandler(int interval); public partial class SetTimeForm : Form { public event OnIntervalChangedEventHandler IntervalChanged; public SetTimeForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int interval = int.Parse(textBox1.Text); if (IntervalChanged != null) { IntervalChanged(interval); } } }
    2009年8月20日 上午 10:13
  • 原來static用多會造成這麼大的問題,因為沒有實際寫大程式的經驗,想再請教一些問題

    甚麼樣的需求才需要把宣告拿去當類別變數呢?因為我看前輩們都只有少數,但我好像把要宣告的都拿去當類別變數

    <int> : 想請問一下這個是甚麼意思? 我沒看過耶,不是誇號?
    2009年8月21日 上午 01:36
  • static 在 MSDN 的用法裡,你會看到指引教學,他會告訴你怎麼用.我已經很久沒研究了.
    在MSDN裡通常每一個指令都會有語法說明和範例.很多人都看二個而已.所以都會亂用.所以要去看指引.他會告訴你為何有這個指令.哪些該用,哪些不該用.

    2009年8月21日 上午 01:55
  • 但是如果要在Main()內使用他會說需要有物件才能參考非靜態型別,像下列這麼寫,加上static才會對,

    好說前輩的寫法要怎樣才不會出現此問題?

    public class Program
        {        
            private System.Timers.Timer showTime;        

            static void Main(string[] args)
            {
                showTime = new System.Timers.Timer();
                showTime.AutoReset = false;
                showTime.Interval = 5000;
                showTime.Enabled = true;
                showTime.Elapsed += new ElapsedEventHandler(P.showTimedEvent);
            }
    2009年8月21日 上午 04:59
  • 你誤會Static的意思了,Static不是不能使用而是非必要不要亂用.
    你看一下上面我PO的Sample Code與好說的有些地方不一樣.
    其實在這個SampleCode內還是可以把static TimeRuner runer這段用其他方式變為區域變數.但因為此程式並不複雜我並未這麼做.
    如果你仔細了解我上面PO的Sample Code你會發現TimeRuner與SetTimerForm互相無任何關係,這代表不論修改TimeRuner或SetTimerForm的內部運作兩者因沒有相關性所以不需要考慮對方的問題.
    但在你的程式中,所有的東西全都混雜再一起,Timer,Form與主程式,所以當你修改任何一方時就有可能會影響到其他部分,這個問題在單工情況可能很好處理,但若在多工程式下會很難Debug,因為有時候無法模擬出發生問題的狀態.
    這也是很多人從單工到多工環境後寫不出程式的原因,多工情況下如果沒有仔細思考程式的架構當程式越堆越大時會發現有修不完的Bug.

    2009年8月21日 上午 05:13
  • 感謝前輩的解說

    但是我還是對錯誤訊息有點疑問,就像上面寫的時候,private System.Timers.Timer showTime; 沒用到static ,要在static的方法內使用就會錯誤
    要求要有物件才能參考非靜態,那上面好說前輩寫的
    public class Program
        {        
            private System.Timers.Timer showTime;        

            static void Main(string[] args)
            {
                showTime = new System.Timers.Timer();
                showTime.AutoReset = false;
                showTime.Interval = 5000;
                showTime.Enabled = true;
                showTime.Elapsed += new ElapsedEventHandler(P.showTimedEvent);
            }
    }


    好說前輩的程式碼
    public class Program
        {
            private System.Timers.Timer showTime;        <-沒加static
            private int reTime = 5;
            private setTime.Form1 set;
            static void Main(string[] args)
            {
                set=new Form1();
                showTime = new System.Timers.Timer();   <-這裡為什麼不會有錯呢?
                showTime.AutoReset = false;
                showTime.Interval = 5000;
                showTime.Enabled = true;
                showTime.Elapsed += new ElapsedEventHandler(set.TimeEventHandle);
                set.SetTimeEvent+=new EventHandler<int>(this.reSet);
                set.ShowDialog();
                Console.Read();
            }




    2009年8月21日 上午 05:29
  • 不行
    Main方法本身是Static method不能存取class member data.只能存取static data.

    應該是他的程式沒注意到.

    2009年8月21日 上午 05:32
  • 我只是隨便寫一寫而已.
    我沒去特別分析你的問題.
    我寫這個範本只是解釋怎麼去寫將偶的程式.
    你用Static 你還是去把MSDN 的指引看完.
    在Windows Form  很少範本會用 Static.但很多人用Sataic 去做全域變數,讓其他的表單容易存取.這個我認為是錯的.
    Static 有很多特性.
    1.初始化時間,在Class變數跟實例變數是不同的.今天比方說,我有一支程式,裡面有三萬個表單.我不知使用者使用哪幾支表單,哪幾項功能.我用靜態的一次就配三萬表單.那不就一開始就掛了.你用實例方式.要的時候在new 在配置.做完後GC就回收.
    2.傳值時是傳參數,傳數值,不是傳表單.一支程式我要設三萬個變數.我是配置三萬個數值的值.要設這個值是new 相關的Form去做處理.處理完保留數值.Form要Dispose掉.
    3.多功,你配個靜態值.每一隻多功的程序在跑.去取該變數值.這多程序改變這個靜態值.而這個靜態值會去影響別支正在跑的值.這個你去更新實例變數是不同的.

    2009年8月21日 上午 05:47