C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: Threading.Timerのイベント発生について


(過去ログ 12 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■3529 / inTopicNo.1)  Threading.Timerのイベント発生について
  
□投稿者/ あら (14回)-(2007/05/14(Mon) 14:32:09)

分類:[C# (Windows)] 

お世話になっております。

System.Threading.Timerで一定間隔で処理を行わせようとしています。
ソリューソン構成を「Debug」時は問題なく動作するのですが、「Release」
時は途中でタイマイベントが発生しなくなります。
私の環境ではループで17回目にタイマイベントが呼ばれなくなります。

タイマイベントを発生しなくなる現象を解消するにはどのように記述
すればよいのでしょうか?

アドバイス等ご教授お願いします。
(Visual Studio 2005 C#)

-------------
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Thread tThread;
        private void Form1_Load(object sender, EventArgs e)
        {
            tThread = new Thread(new ThreadStart(AAA));
            tThread.IsBackground = true;
            tThread.Start();
        }

        public void AAA()
        {
            AutoResetEvent autoEvent = new AutoResetEvent(false);
            StatusChecker statusChecker = new StatusChecker();

            TimerCallback timerDelegate = new TimerCallback(statusChecker.CheckStatus);
            System.Threading.Timer stateTimer = new System.Threading.Timer(timerDelegate, autoEvent, 0, 100);

            int i = 0;

            while (true)
            {
                SetText("### i:" + (i++).ToString() + Environment.NewLine);
                autoEvent.WaitOne();
            }
        }

        delegate void SetTextCallback(string text);
        public void SetText(string text)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.richTextBox1.AppendText(text);
            }
        }
    }

    class StatusChecker
    {

        // This method is called by the timer delegate.
        public void CheckStatus(Object stateInfo)
        {
            AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
            Debug.WriteLine("{0} Checking status",
                DateTime.Now.ToString("h:mm:ss.fff"));

            autoEvent.Set();
        }
    } 

引用返信 編集キー/
■3536 / inTopicNo.2)  Re[1]: Threading.Timerのイベント発生について
□投稿者/ 囚人 (97回)-(2007/05/14(Mon) 16:19:52)
TimerCallback のインスタンスである timerDelegate のスコープを Form1 のメンバなどにして消えないようにして下さい。もしくは、メソッドの最後で触ってみるとか(null 代入は最適化されて無意味になるので他の方法を)。
メソッドAAA でループしているので timerDelegate のインスタンスは GC の対象にならないと思うのが普通ですが、

System.Threading.Timer stateTimer = new System.Threading.Timer(timerDelegate, autoEvent, 0, 100);

の以後、timerDelegate は使用されていないので、上記の式実行後、timerDelegate は GC の対象になります。メソッド内で有効なローカル変数がメソッドを抜けるまで GC の対象にはならないと考えない事です。

デバッガにアタッチしていたり最適化されていない場合は、今回のようなローカル変数はメソッドを抜けるまで GC の対象とならないように IL が書き換えられています。(だったと思います。プログラミング .NET Framework に記述があった記憶が)
なので、Release ビルドした途端動かないという現象に出くわします。
引用返信 編集キー/
■3537 / inTopicNo.3)  Re[2]: Threading.Timerのイベント発生について
□投稿者/ 囚人 (98回)-(2007/05/14(Mon) 16:22:32)
間違い。

stateTimer

のスコープを広げて下さい。
引用返信 編集キー/
■3538 / inTopicNo.4)  Re[3]: Threading.Timerのイベント発生について
□投稿者/ 囚人 (99回)-(2007/05/14(Mon) 16:26:07)
という事で、

一番手っ取り早いのは、stateTimer を using で囲むか、while ループの後で stateTime.Dispose() しておくかです。
これで多分、少なくとも while を抜けるまでは GC に消されません。
引用返信 編集キー/
■3543 / inTopicNo.5)  Re[4]: Threading.Timerのイベント発生について
□投稿者/ あら (15回)-(2007/05/14(Mon) 19:48:51)
返信ありがとうございます。

教えて頂いた
>stateTimer を using で囲む
のやり方で解決できました。

ありがとうございます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -