使用内联参数的Groupbox计时器

时间:2016-09-08 21:54:47

标签: c# .net winforms timer

我无法理解为什么我的groupbox的已用计时器中的某个参数不起作用。

我的开发团队和我有许多不同的应用程序,我们希望为这些应用程序提供集中的通知位置。所以我创建了一个存储一些基本信息的数据库(应用程序名称,刷新频率等)。

所以我目前正在做的是使用FlowLayoutPanel并为我们拥有的所有应用程序动态创建Groupboxes。如果登录用户至少有一个该应用程序的通知,我想创建一个带有计时器的组合框(将刷新与该应用程序关联的所有方法)。这很好,它看起来像这样:App GroupBoxes

当用户单击标签时,它会启动应用程序,然后处理组框。当发生这种情况时,该组箱的计时器将启动,当它被删除时,如果用户有任何通知,它将重新创建该组箱。

我遇到的问题出在我的代码中:

GroupBox gbItem = new GroupBox();
gbItem.Text = lstDistinctApps[i];
gbItem.Tag = Convert.ToInt32(_dtNotifications.Rows[j]["Frequency"]);
gbTimer.Interval = Convert.ToInt32(gbItem.Tag) * 5000;
gbTimer.Elapsed += (sender, e) => GBTimerElapsed(sender, e, gbItem.Text, Convert.ToInt32(gbItem.Tag));
gbTimer.Start();

过去的事件:

private void GBTimerElapsed(object sender, System.Timers.ElapsedEventArgs e, string appName, int frequency)
{
        //Dynamically creates a groupbox timer for that groupbox and during the elapsed event it refreshes the notifications for that app
        ReloadNotificationGroupBox(appName);
        System.Timers.Timer tmr = sender as System.Timers.Timer;
        tmr.Dispose();
}

当用户点击GroupBox内的标签时,会运行以下代码:

 int refreshFreq = Convert.ToInt32(label.Parent.Tag);//GetAppRefreshFrequency(label.Parent.Text);
 if (refreshFreq != 0)
 {        
    label.Parent.Dispose();
    //TODO: Dispose old timer associated with the group
 }

我可以点击已经过去的事件就好了但是当GroupBox被释放时,appName出现空白但频率就在那里。我已经尝试了很多东西,例如将appName放在gbItem.Tag字段中,但是我点击了已经过去的事件,它又是空白的。 我尝试的最后一件事是写这个:

string appName = gbItem.Text;
gbTimer.Elapsed =+ (sender, e) => GBTimerElapsed(sender, e, appName, Convert.ToInt32(gbItem.Tag));

我能够以频率获取appName。 我一直在试图弄清楚当物体被丢弃时如何保留频率。

我没有正确处理GroupBox吗? 或者有更好的方法来做我想做的事情吗?

1 个答案:

答案 0 :(得分:0)

如果没有好的Minimal, Complete, and Verifiable code example,就无法完全理解您的代码和上下文。所以我会专注于可以肯定地看到的......

  

我能够以频率获取appName。我一直在试图弄清楚当物体被丢弃时如何保留频率。

这取决于如何实现两个不同的属性TextTag。从技术上讲,在处理对象后,您不应该访问 属性。但只有Text属性才是至关重要的。 Tag属性严格按照.NET功能实现。本机API中的粗略等价物可能类似于SetWindowLong(),但由于Tag必须处理托管对象,因此将其用作底层实现是没有意义的。

但是Text属性确实直接对应于本机API的“窗口文本”的概念,因此该属性通过本机Windows API,使用GetWindowText()来检索窗口的文本。如果控件的窗口句柄无效(例如,您已放置控件),则仅当文本缓存在对象的text字段中时才会返回。只有当窗口句柄当前无效时才设置该值(在您的情况下不是这种情况),才会发生这种情况。

实际上,对于最可靠和一致的代码,您可能应该同时处理这两个属性。即如果要在订阅计时器事件时检索当前值,则应将它们分配给局部变量并在匿名方法中使用它们,以便通过匿名方法和值捕获这些局部变量你关心的是在适当的时候使用。

例如:

GroupBox gbItem = new GroupBox();
string text = lstDistinctApps[i];
int frequency = Convert.ToInt32(_dtNotifications.Rows[j]["Frequency"]);
gbItem.Text = text;
gbItem.Tag = frequency;
gbTimer.Interval = frequency * 5000;
gbTimer.Elapsed += (sender, e) => GBTimerElapsed(sender, e, text, frequency);
gbTimer.Start();

FWIW,请注意,虽然我无法代表frequency值的初始检索,但是在您输入int值后,您无需拨打Convert.ToInt32()转换回int。一个简单的案例就足够了。当然,如果你能(如上所述)只保留正确类型的变量中的值并直接使用它,那就更好了。

  

我没有正确处理GroupBox吗?或者有更好的方法来做我想做的事情吗?

“更好”是主观的,尤其是在这里。问题中的信息不多。也就是说,我没有看到任何关于您共享的代码特别令人不安的问题,除了诸如Convert.Int32()的额外调用等不需要的细微细节之外。

如果您不确定自己已完成计时器,则可能会发现代码更好。实现这一目标的一种方法可能是在处理对象之前继续并停止计时器。但是你想切换到使用System.Windows.Forms.Timer,以便确保在处理对象后防止定时器事件发生。