使用 Windows 窗体计时器从不同的类中触发方法
本文关键字:方法 窗体 Windows 计时器 使用 | 更新日期: 2023-09-27 18:30:15
抱歉,如果已经有答案了,但我挖了很多,发现的很少。
我正在尝试在 C# .NET 4.5 Windows 窗体应用程序上实现一个看门狗系统。 基本上,我有一个带有各种按钮、文本显示等的表单,可以连接到外部设备。 我在主窗体上有一个计时器,应该每 250 毫秒左右检查一次设备是否有变化。
我将所有 MainPage 表单代码(包括计时器)集中到一个类中,并将外部设备的代码集中到从 MainPage 继承的自己的类中。 问题是,我希望能够让计时器的 Tick() 函数调用 Device 类的方法。 以下是简化的代码:
namespace MyApplication
{
public partial class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public static void SetTextBox(string Message)
{
Textbox_Status.Text = Message;
}
private void timer1_Tick(object sender, EventArgs e)
{
Device.DeviceCheck();
}
}
public class Device : MainPage
{
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
}
当然,我不能从计时器中调用Device.DeviceCheck
,因为它不是静态的。 但是,如果我声明 DeviceCheck 静态,我现在会收到一个错误,指出Textbox_Status
不是静态的。 如果我试图声明它是静态的,Visual Studio会非常生我的气!
最初,我将所有内容都转储到同一个类中,并且一切正常,但这是非常丑陋的代码。 有没有更好的方法?
编辑:额外的障碍=需要由DeviceCheck()更改的形式中的多个事物
所以我在简化的代码中省略了什么:除了 SetTextBox() 方法之外,我还有一个基于来自 DeviceCheck 的信息设置一些指标的方法:
public void SetImages(string Image)
{
switch(Image)
{
case "Green":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = false;
break;
case "Red":
Image_BlackDataKeyDim.Visible = true;
Image_RedDataKeyDim.Visible = false;
Image_GreenDataKeyDim.Visible = true;
break;
case "Black":
Image_BlackDim.Visible = false;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
case "None":
default:
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
}
}
当然,当我构建表单时,我的所有指标也都已到位,因此它们也不能是静态的。 因此,DeviceCheck
返回要显示的字符串消息是有效的,但我不能真正让它也返回SetImages()
使用的字符串。
井。。。我可以通过返回具有多个字符串的结构来,但是有更好的方法吗?
编辑:这是我的工作解决方案,基于埃里克的建议:
我从状态元素的结构开始:
public struct Dev_status
{
public string Indicator1;
public string Indicator2;
public DK_status(string indicator1, string indicator1)
{
this.Indicator1 = indicator1;
this.Indicator2 = indicator2;
}
}
public static Dev_status status = new Dev_status(Device.Messages.thing1_offline,Device.Messages.thing2_offline);
指标现在从status
获取消息:
public void SetStatusBoxes()
{
Textbox_thing1_Status.Text = status.Indicator1;
Textbox_thing2_Status.Text = status.Indicator2;
}
public void SetImages()
{
string IndicatorColor = "None";
if (status.Indicator2 == Device.Messages.GreenThing) IndicatorColor = "Green";
else if (status.Indicator2 == Device.Messages.RedThing) IndicatorColor = "Red";
else if (status.Indicator2 == Device.Messages.BlackThing) IndicatorColor = "Black";
switch(IndicatorColor)
{
case "Green":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = false;
break;
case "Red":
Image_BlackDim.Visible = true;
Image_RedDim.Visible = false;
Image_GreenDim.Visible = true;
break;
case "Black":
Image_BlackDim.Visible = false;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
case "None":
default:
Image_BlackDim.Visible = true;
Image_RedDim.Visible = true;
Image_GreenDim.Visible = true;
break;
}
}
计时器只是调用 DeviceCheck
方法并设置指标:
private void timer1_Tick(object sender, EventArgs e)
{
status = Device.DeviceCheck();
SetStatusBoxes();
SetImages();
}
最后,DeviceCheck
为状态结构设置值,该结构是公共的、静态的,并由 Device
类继承:
public static void DeviceCheck()
{
//Code that checks the device status
status.Indicator1 = CheckDeviceConnected();
status.Indicator2 = CheckDeviceType();
}
这非常无缝地工作。 最后,我毕竟不需要从DeviceCheck
返回值。 不过,我仍然会将这个想法标记为被接受,因为它将我引向了正确的方向。
如果你
1)让DeviceCheck()在文本框中返回您想要的字符串(而不是设置文本框)
2) 在 timer1_Tick() 中,使用来自 DeviceCheck 的返回值设置文本框。
喜欢这个:
namespace MyApplication
{
public partial class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public static void SetTextBox(string Message)
{
Textbox_Status.Text = Message;
}
private void timer1_Tick(object sender, EventArgs e)
{
string result = Device.DeviceCheck();
SetTextBox(result);
}
}
public class Device : MainPage
{
public string DeviceCheck()
{
//Do other stuff here
return("Some text");
}
}
}
我在这里看到了两个明显的选择:将DeviceCheck()
声明为子类要实现的抽象方法,或者以某种方式公开计时器tick事件。
抽象方法:
public partial abstract class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public void SetTextBox(string message)
{
Textbox_Status.Text = message;
}
protected abstract void DeviceCheck();
private void timer1_Tick(object sender, EventArgs e)
{
DeviceCheck();
}
}
public class Device : MainPage
{
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
事件:
public partial abstract class MainPage : Form
{
public MainPage()
{
InitializeComponent();
}
public void SetTextBox(string message)
{
Textbox_Status.Text = message;
}
protected event EventHandler TimerTick;
private void timer1_Tick(object sender, EventArgs e)
{
EventHandler handler = TimerTick;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
public class Device : MainPage
{
public Device()
{
TimerTick += (sender, e) => DeviceCheck();
}
public void DeviceCheck()
{
//Do other stuff here
SetTextBox("Some text");
}
}
另一个建议的答案也应该有效,假设static
已从SetTextBox()
方法中删除。但是根据您的评论,听起来消息处理(即string
值)只是您想要执行的操作的一部分。不过,您仍然可以遵循该建议,但是您将传递某种聚合对象而不是string
,即具有多个属性的简单容器类,包括消息string
和您需要的任何其他值。