C#报警系统循环问题

时间:2017-07-22 18:35:13

标签: c# asynchronous callback system alarm

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

到目前为止一切正常,除了当2行包含相同的日期/时间时,警报将触发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语句,一切都可以正常运行。

提前致谢!

3 个答案:

答案 0 :(得分:1)

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

如果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);
    }
}

答案 1 :(得分:0)

您可以在致电break后提出Alert.Show()

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
        }
    }
}

答案 2 :(得分:0)

我发现@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);
    }
}

谢谢!