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 // 等等...

我对计时器和线程的了解还不足以检测为什么线程“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());
        }
    }
}
4

3 回答 3

0

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

于 2013-05-23T15:57:17.860 回答
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;
    }
于 2013-05-23T16:44:31.383 回答
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();
            }*/
        }
于 2013-05-23T19:40:28.387 回答