1

Winform (C#) で非常に単純なプログラムを作成しています。

ただし、スレッドとタイマーに問題があります。「スレッド '' (0x1e30) がコード 0 (0x0) で終了しました」というメッセージが表示されます。これは、スレッドが正常に停止したときに発生することを読みました。しかし、これは私が望むものではありません。

番組は「今何してる?」その目的は、トレイに座って、ランダムな時間間隔 (たとえば、15 分から 120 分の間) でテキスト プロンプトが表示され、現在何をしているかを書き留めるように求めることです。これは、単純な txt ファイルに記録されます。自分がしていることを「告白」しなければならないという単純な行為が、コンピューターの前で自分の時間をどのように過ごしているかについて、より意識的になる (そしてうまくいけば、より生産的になる) という考えです。

アプリの画像

テキスト (「Browsing StackOverflow」など) を書き込んだとき、再びトレイに最小化され、いつポップアップするかを示す新しいカウントダウンが開始されます。

問題は、何らかの理由でメインスレッドがしばらくして停止し、それによってタイマーも停止することです。理由はわかりません。Visual Studio 2012 で WinForm プロジェクトを作成するときにデフォルトで作成されるもの以外のスレッドでは何もしませんでした。

出力をログに記録すると、次のようになります (コメントを追加しました)。

  • 5 // アプリがカウントダウンを開始
  • 4
  • 3
  • 2
  • 1
  • 0 // タイマーが終了し、ウィンドウを表示して「Go!」を押すのを待ちます。ボタン
  • 4 // 新しいカウントダウン
  • 3
  • 2
  • 1
  • 0 // ウィンドウを (意図したとおりに) 表示しない?
  • 0
  • スレッド '' (0x6e0) はコード 0 (0x0) で終了しました。
  • 0
  • 0 // など...

タイマーとスレッドに関する私の知識は、スレッド「名前なし」がその特定の瞬間に停止する理由を検出できるほど十分ではありません。

これが私のコードです (重要度の低いコードをいくつか削除しました。すべてここで確認できます: http://pastebin.com/5Apfgcpy ):

namespace WhatAreYouDoingRightNow
{
public partial class Form1 : Form
{
private string _text; // text that the user will write to
private double _timeLeft; // countdown time

public Form1()
{
    InitializeComponent();

    label2.Visible = true; // debug label to show timer

    this.WindowState = FormWindowState.Minimized; // start minimized in tray

    _text = ""; // reset text
    WriteLog(true); // write for the first time of today

    GetRandomTime(); // get new random time interval

    timer1.Interval = 1000; // seconds
    timer1.Start(); // start timer
}

// Go button (either by click or hitting Enter)
private void HitGoButton()
{
    _text = DateTime.Now + " - " + textBox1.Text; // append date and time
    WriteLog(false);

    _text = "";
    GetRandomTime();
    this.WindowState = FormWindowState.Minimized;
}

// Open txt file and write to it
private void WriteLog(bool startOfTheDay)
{
    // writes to a txt file using StreamWriter
}

private void GetRandomTime()
{
    Random rand = new Random((int) DateTime.Now.Ticks);

    _timeLeft = rand.Next(1, 2)*5; // multiplied by 60 to get    minutes instead of seconds
}


// Count down to random time and then display the box
private void timer1_Tick(object sender, EventArgs e)
{
    // count down
    if (_timeLeft > 0)
        _timeLeft--;

    label2.Text = _timeLeft.ToString(); // debug label to show time
    notifyIcon1.Text = _timeLeft.ToString(); // debug show time in tray
    Console.WriteLine(_timeLeft); // debug write time to console window

    // if time ran out --> show the window
    if (_timeLeft <= 0)
    {
        this.WindowState = FormWindowState.Normal;
    }
}



private void button1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
        HitGoButton();
}

private void Form1_Resize_1(object sender, EventArgs e)
{
    if (WindowState == FormWindowState.Minimized)
    {
        this.Hide(); // only show in tray icon, not in task bar
    }
    else if (WindowState == FormWindowState.Normal)
    {
        this.Show();
    }
}
  }
}

私のプログラムが 1 回しか動作せず、その後スレッドを終了してカウントを停止する理由を誰かが理解できますか?

前もって感謝します!

更新 1:これもデザイナー ファイルです: http://pastebin.com/yvWs2VVp

更新 2: Program.cs のコードは次のとおりです (何も変更していません)。

namespace WhatAreYouDoingRightNow
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}
4

3 に答える 3

0

間違っていたら訂正してください。15 分から 120 分の間のランダムな時間にウィンドウをポップアップさせたいと思われますか? これをいくつかのステップに分割します。

第一歩

その場合、GetRandomTimeメソッドは次のようになります。

private void GetRandomTime()
    {
        Random rand = new Random(); /*You do not need to supply it the current
 datetime as the random class uses a time dependent default seed value */

//look at the constructor http://msdn.microsoft.com/en-us/library/system.random.aspx 

        _timeleft = rand.Next(15, 120) * 60 * 1000; /*here you are telling the random 
"I want any number between 15 and 120 but in order to get this to vibe with the timer's
 interval format you need to multiply by 60 first for the seconds and 1000 to convert
 to milliseconds. */

    }

したがって、基本的に上記のランダムから、たとえば 24 になると.. 60 を掛けて 1440 を取得し、次に 1000 を掛けて 1440000 を取得します。これは、24 分間に何ミリ秒あるかを示します。あなたが以前持っていたものは、常にあなたに 5 を与えるでしょう。ステップ 2 に進みます..

ステップ2

次に、ティックハンドラーを変更する必要があります

private void timer1_Tick(object sender, EventArgs e)
    {
        // count down
        if (_timeLeft > 0)
            _timeLeft = _timeleft - 1000; //Since your interval is 1s subtract that.

        label2.Text = ((_timeLeft / 1000) / 60).ToString() + " minutes left"; // convert back to minutes
        notifyIcon1.Text = ((_timeLeft / 1000) / 60).ToString() + " minutes left"; 
        Console.WriteLine(((_timeLeft / 1000) / 60).ToString() + " minutes left"); 

        // if time ran out --> show the window
        if (_timeLeft <= 0)
        {
            this.WindowState = FormWindowState.Normal;
        }
    }

より迅速にデバッグするために、random メソッドをハードコーディングされた 1 になるように変更することをお勧めします。その後、プログラムが 1 分ごとに閉じて再び開くかどうかを確認します。

//Debugging version of GetRanomdTime
    private void GetRandomTime()
    {
        //Random rand = new Random((int)DateTime.Now.Ticks);

        _timeleft = 1 * 60 * 1000;
    }
于 2013-05-23T16:44:31.383 に答える