C#报警系统循环问题

C# Alarm system loop issue

我要建立一个警报系统。它的工作方式是从 gridview 列中提取 date/time 信息,然后我使用异步操作来检查现在的时间何时等于 gridview date/time 列中的一行或多行,如果然后显示警报。

到目前为止一切正常,除了当 2 行包含相同的 date/time 时,警报将触发 4 次而不是 2 次。这是我目前得到的结果:

    string firma = "";
    private void radButton1_Click(object sender, EventArgs e)
    {
        try
        {
            for (int i = 0; i < radGridView4.Rows.Count; i++)
            {
                DateTime executionTime = Convert.ToDateTime(radGridView4.Rows[i].Cells[10].Value.ToString());
                ScheduleAction(action, executionTime);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    public async void ScheduleAction(Action action, DateTime ExecutionTime)
    {
        try
        {
            if (DateTime.Now < ExecutionTime)//ExecutionTime only create an alarm for rows that are later than now
            {
                await Task.Delay((int)ExecutionTime.Subtract(DateTime.Now).TotalMilliseconds);

                action();
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    public void action()
    {
        RadDesktopAlert Alert;
        for (int i = 0; i < radGridView4.Rows.Count; i++)
        {
            DateTime executionTime = Convert.ToDateTime(radGridView4.Rows[i].Cells[10].Value.ToString());

            if (DateTime.Now.Date == executionTime.Date && DateTime.Now.Hour == executionTime.Hour && DateTime.Now.Minute == executionTime.Minute)
            {
                Alert = new RadDesktopAlert();

                firma = radGridView4.Rows[i].Cells[2].Value.ToString();

                Alert.CaptionText = "Telefonmøde";
                Alert.ContentText = firma;
                Alert.Show();

            }
        }
    }

感谢任何帮助,即使没有 try 语句,一切也能正常运行。

提前致谢!

部分问题是您安排重复警报,另一部分是您的操作也将触发 重复警报,因为这两个代码块都在您的网格中循环。

如果 action 方法不依赖于网格中的数据,而是通过它的参数获取所需的一切,这可能会有所帮助。这意味着我们应该在第一次遍历网格项时捕获 content,然后将此信息传递给方法。

为此,我们可以修改action方法,将内容取字符串,去掉网格的循环。请注意,如果我们现在调用 action,它会立即执行操作,因此由调用者在正确的时间安排它:

public void action(string content)
{
    var alert = new RadDesktopAlert
    {
        CaptionText = "Telefonmøde",
        ContentText = content
    };

    alert.Show();
}

既然我们已经修改了action 方法,我们还需要修改ScheduleAction 方法,以便它传递新的必需参数。这意味着它还需要采用一个新参数:

public async void ScheduleAction(Action<string> action, string content, 
    DateTime ExecutionTime)
{
    if (DateTime.Now < ExecutionTime)
    {
        await Task.Delay((int)ExecutionTime.Subtract(DateTime.Now).TotalMilliseconds);
        action(content);
    }
}

接下来,我们可以创建一个单独的 List<DataTime> 对象来跟踪我们已经安排好的时间。然后,当我们遍历网格视图时,我们只安排一个不在列表中的时间。我们还捕获了 content 数据:

var scheduledExecutionTimes = new List<DateTime>();

for (int i = 0; i < radGridView4.Rows.Count; i++)
{
    DateTime executionTime = Convert.ToDateTime(radGridView4.Rows[i].Cells[10].Value.ToString());

    if (!scheduledExecutionTimes.Contains(executionTime))
    {            
        string content = radGridView4.Rows[i].Cells[2].Value.ToString();
        ScheduleAction(action, content, executionTime);

        // Add this time to our list
        scheduledExecutionTimes.Add(executionTime);
    }
}

您可以在调用 Alert.Show() 后输入 break:

public void action()
{
    RadDesktopAlert Alert;
    for (int i = 0; i < radGridView4.Rows.Count; i++)
    {
        DateTime executionTime = Convert.ToDateTime(radGridView4.Rows[i].Cells[10].Value.ToString());

        if (DateTime.Now.Date == executionTime.Date && DateTime.Now.Hour == executionTime.Hour && DateTime.Now.Minute == executionTime.Minute)
        {
            Alert = new RadDesktopAlert();

            firma = radGridView4.Rows[i].Cells[2].Value.ToString();

            Alert.CaptionText = "Telefonmøde";
            Alert.ContentText = firma;
            Alert.Show();
            break; // This will prevent duplicate alarms
        }
    }
}

我发现@Rufus L 的解决方案非常有用,我在 3 个代码块中所做的唯一更改是删除 if (!scheduledExecutionTimes.Contains(executionTime)) 以实现我的目标。希望这对其他人有用,因为这对我来说是一场斗争。

    var scheduledExecutionTimes = new List<DateTime>();

for (int i = 0; i < radGridView4.Rows.Count; i++)
{
    DateTime executionTime = Convert.ToDateTime(radGridView4.Rows[i].Cells[10].Value.ToString());

    if (!scheduledExecutionTimes.Contains(executionTime))
    {            
        string content = radGridView4.Rows[i].Cells[2].Value.ToString();
        ScheduleAction(action, content, executionTime);

        // Add this time to our list
        scheduledExecutionTimes.Add(executionTime);
    }
}

谢谢!