自动注销C#桌面应用程序的问题

时间:2011-05-19 16:53:30

标签: c# winforms timer

我需要在C#中实现自动注销功能。以前我问了一个类似的问题before,我设法使用System.Windows.Forms.Timer实现它。但是现在除了在用户移动鼠标或输入密钥时重置计时器之外我还有一个额外的要求我还需要在通过串行端口(DataReceived事件处理程序)接收到新消息时重置计时器。

serialPort.DataReceived += port_DataRecieved;

我需要在port_DataRecieved函数的一部分中包含reset函数。我不能简单地向serialPort.DataReceived添加另一个委托方法,它将执行重置,因为serialPort.DataReceived将收到很多我不感兴趣的其他消息。我想在我感兴趣的消息时执行重置到达。我知道在哪里放置重置功能。问题是计时器不会在port_DataRecieved方法中重置。并且我无法使用System.Threading.Timer实现所需的结果。任何人都可以指导我或就此问题提供一些建议吗?所提供的任何帮助都会得到很大的帮助。

public partial class Form1: Form
{  

    private System.Windows.Forms.Timer sessionTimer = new System.Windows.Forms.Timer();

    public Form1()
    {
        initialiseTimer(); 
    } 

    private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            serialPort= (SerialPort)sender;
            str = serialPort.ReadExisting();
            string[] split = str.Split(Convert.ToChar(10));
            for (int i = 1; i < split.Length; i++)
            {
                str = split[i];
                if (split[i].StartsWith("+CMTI:"))
                {
                    sessionTimer.Stop();
                    sessionTimer.Start();

                    //Other codes
                }
            }
        }
        catch (Exception)
        {
            MessageBox.Show("Error processing received commands !", "CONNECTION ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            sendRecPort.Close();
        }
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        sessionTimer.Stop();
        sessionTimer.Start(); 
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        sessionTimer.Stop();
        sessionTimer.Start(); 
    }

    private void initialiseTimer()
    {
        sessionTimer.Interval = (5 * 60 * 1000);        
        sessionTimer.Tick += new EventHandler(logOutUser);
        sessionTimer.Stop();
        sessionTimer.Start();
    }

    private void logOutUser(object sender, EventArgs e)
    {
        // logout the user
        this.Hide();
        //Open up the login Form
        login.Show();
    }

}

2 个答案:

答案 0 :(得分:2)

您的问题是在{i}线程以外的线程上执行DataReceived事件。您正在尝试从非UI线程修改计时器(UI对象)。这通常会引发异常,但发出DataReceived事件的方法可能会吞噬该异常。

来自DataReceived事件的documentation

  

在a上引发DataReceived事件   接收数据时的辅助线程   来自SerialPort对象。因为   这个事件是在次要事件上提出的   线程,而不是主线程,   试图修改一些元素   主线程,如UI元素,   可能引发线程异常。如果   有必要修改元素   主要表格或控制,发布更改   使用Invoke返回请求,这将是   在适当的线程上完成工作。

您需要与UI线程同步以设置计时器。

void ResetTimer()
{
    sessionTimer.Stop();
    sessionTimer.Start();
}

private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
    //Other codes
    this.Invoke((MethodInvoker)delegate { ResetTimer(); });
    //Other codes
}

答案 1 :(得分:0)

  

我需要在port_DataReceived函数的一部分中包含reset函数。

确定。疑难杂症。

  

我不能简单地向serialPort.DataReceived添加另一个委托方法,这将执行重置,因为serialPort.DataReceived将收到许多我不感兴趣的其他消息。

好的,但我以为你说过:

  

我希望在我感兴趣的邮件到达时执行重置。

所以你拥有来监听DataReceived方法,或者不会知道该消息何时到达。

我很困惑。你想做什么?魔法?

if (dataReceived == "someValue1") 
{
  //action if matches "someValue1"
}
else if (dataReceived.Contains("someValue2"))
{
  // action if contains "someValue2"
}
else if (dataReceived.IndexOf("someValue3") != -1 )
{
  // action if contains "someValue3"
}
else if (dataReceived == "someValue4")
{
  // action if matches "someValue4"
}
else
{
  // default action
}