C#控制台程序编译报错:非静态字段_timer需对象引用,求解决方案
解决C#静态方法访问非静态字段的定时器错误
错误原因
An object reference is required for the non-static field, method, or property "Program._timer"
这个错误的核心是静态方法无法直接访问类的非静态成员:Main是静态方法,属于类本身;而_timer是类的实例字段,属于类的具体对象。两者上下文不同,所以静态方法里直接给_timer赋值会编译失败。
同时你代码里还有一个逻辑问题:mre.WaitOne()放在了定时器初始化代码之前,程序会先阻塞在这里,永远不会执行到创建定时器的步骤,必须调整顺序。
解决方案一:将_timer改为静态字段
最简单的修改方式是把_timer声明为静态字段,让它和Main方法同属静态上下文:
using System; using System.Xml.Linq; using Microsoft.Win32; using static Microsoft.Win32.SystemEvents; using System.Collections.Generic; using System.Linq; using System.Xml; using System.Diagnostics.Metrics; using System.Timers; using System.Threading; namespace CSharpTutorials { class Program { // 修改为静态字段 private static System.Threading.Timer _timer = null; public static void Main() { DateTime lastLogin, lastLock; string bossEmail; XDocument doc = XDocument.Load("properties.xml"); XElement lastLockElement = doc.Descendants("lastLock").FirstOrDefault(); XElement lastLoginElement = doc.Descendants("lastLogin").FirstOrDefault(); SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; var mre = new ManualResetEvent(false); Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e) { mre.Set(); }; // 先初始化定时器,再阻塞等待退出信号 _timer = new System.Threading.Timer(TimerCallback, null, 0, 2000); mre.WaitOne(); } private static void TimerCallback(Object o) { Console.WriteLine("In TimerCallback: " + DateTime.Now); } public static string GetTimestamp(DateTime value) { return value.ToString("yyyy/MM/dd HH:mm:ss"); } static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) { string timeStamp = GetTimestamp(DateTime.Now); XDocument doc = XDocument.Load("prefrences.xml"); switch (e.Reason) { case SessionSwitchReason.SessionLogon: XElement logonElement = doc.Descendants("lastLogin").FirstOrDefault(); if (logonElement != null) { logonElement.SetAttributeValue("lastLogin", DateTime.Now); doc.Save("properties.xml"); } break; case SessionSwitchReason.SessionLock: XElement lockElement = doc.Descendants("lastLock").FirstOrDefault(); if (lockElement != null) { lockElement.SetAttributeValue("lastLock", DateTime.Now); doc.Save("properties.xml"); } break; case SessionSwitchReason.SessionLogoff: case SessionSwitchReason.RemoteConnect: case SessionSwitchReason.RemoteDisconnect: case SessionSwitchReason.SessionUnlock: default: break; } } } }
解决方案二:使用类实例访问非静态字段
如果希望保持_timer为实例字段,可以创建Program类的对象,通过对象访问字段:
using System; using System.Xml.Linq; using Microsoft.Win32; using static Microsoft.Win32.SystemEvents; using System.Collections.Generic; using System.Linq; using System.Xml; using System.Diagnostics.Metrics; using System.Timers; using System.Threading; namespace CSharpTutorials { class Program { private System.Threading.Timer _timer = null; public static void Main() { DateTime lastLogin, lastLock; string bossEmail; XDocument doc = XDocument.Load("properties.xml"); XElement lastLockElement = doc.Descendants("lastLock").FirstOrDefault(); XElement lastLoginElement = doc.Descendants("lastLogin").FirstOrDefault(); SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; var mre = new ManualResetEvent(false); Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e) { mre.Set(); }; // 创建Program实例 Program app = new Program(); // 通过实例初始化定时器 app._timer = new System.Threading.Timer(app.TimerCallback, null, 0, 2000); mre.WaitOne(); } // 修改为非静态方法 private void TimerCallback(Object o) { Console.WriteLine("In TimerCallback: " + DateTime.Now); } public static string GetTimestamp(DateTime value) { return value.ToString("yyyy/MM/dd HH:mm:ss"); } static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) { string timeStamp = GetTimestamp(DateTime.Now); XDocument doc = XDocument.Load("prefrences.xml"); switch (e.Reason) { case SessionSwitchReason.SessionLogon: XElement logonElement = doc.Descendants("lastLogin").FirstOrDefault(); if (logonElement != null) { logonElement.SetAttributeValue("lastLogin", DateTime.Now); doc.Save("properties.xml"); } break; case SessionSwitchReason.SessionLock: XElement lockElement = doc.Descendants("lastLock").FirstOrDefault(); if (lockElement != null) { lockElement.SetAttributeValue("lastLock", DateTime.Now); doc.Save("properties.xml"); } break; case SessionSwitchReason.SessionLogoff: case SessionSwitchReason.RemoteConnect: case SessionSwitchReason.RemoteDisconnect: case SessionSwitchReason.SessionUnlock: default: break; } } } }
内容的提问来源于stack exchange,提问作者Zac Borders
相关产品推荐
相关产品推荐

