Winform app:线程和计时器的问题

时间:2013-05-23 15:47:13

标签: c# winforms visual-studio timer threadpool

我在Winform(C#)中创建了一个非常简单的程序。

但是,我遇到线程和计时器的问题。我收到一条名为“线程'(0x1e30)已退出的消息,代码为0(0x0)。”我已经读过,当线程成功停止时会发生这种情况。但是,这不是我想要的。

该计划名为“你现在在做什么?”它的目的是坐在托盘中,随机的时间间隔(比如15到120分钟)弹出一个文字提示,让我写下我现在正在做的事情。然后将其记录到一个简单的txt文件中。我的想法是,仅仅“承认”我正在做的事情的行为将使我更加清楚我是如何在电脑前度过的(并希望提高工作效率)。

Picture of the app

当我写了一些文字(例如“浏览StackOverflow”)时,它会再次最小化到托盘并开始新的倒计时以便弹出。

问题是主线程在某段时间后停止运行,从而使计时器停止。我不知道为什么;在Visual Studio 2012中创建WinForm项目时,我没有对默认情况下的线程做任何事情。

记录输出时,它看起来像这样(我附加了注释):

  • 5 //应用程序开始倒计时
  • 4
  • 3
  • 2
  • 1
  • 0 //计时器完成,显示窗口并等待点击“Go!”按钮
  • 4 //新倒计时
  • 3
  • 2
  • 1
  • 0 //不显示窗口(按预期)?
  • 0
  • 线程''(0x6e0)已退出,代码为0(0x0)。
  • 0
  • 0 //等......

我对定时器和线程的了解不足以能够检测到“No Name”线程在特定时刻停止的原因。

这是我的代码(我删除了一些不那么重要的代码;你可以在这里看到所有代码: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:以下是设计师档案: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());
        }
    }
}

3 个答案:

答案 0 :(得分:0)

当表单显示给用户时,您不应该停止计时器吗?然后在隐藏时重新启用倒计时。

答案 1 :(得分: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.现在进入第二步......

第二步

现在您需要更改刻度线处理程序

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;
        }
    }

为了更快地进行调试,我建议您更改随机方法,为您提供硬编码1.然后查看您的程序是否每1分钟关闭并再次打开。

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

        _timeleft = 1 * 60 * 1000;
    }

答案 2 :(得分:0)

我发现了问题所在。显然,我在Form的Resize事件中重写了一些功能,导致程序无法工作。

如果我注释掉以下内容,该程序将按预期工作:

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();
            }*/
        }
相关问题