Пусть MessageBox появится один раз (код внутри таймера) - PullRequest
0 голосов
/ 02 апреля 2012

ОБНОВЛЕНИЕ: мне удалось решить мою проблему. Используя приведенный ниже код, я переместил свой MessageBox ПОСЛЕ сохранения в XML и изменил таймер с 100 мс до 400 мс. У меня сейчас 1 коробка появляется, слава богу. Хотя, если у кого-то есть быстрый способ обновления одного значения (ActReminded) в массиве List (ActListTask), это было бы здорово знать.

У меня небольшая проблема с отображением MessageBox. Показать внутри таймера без спама. Вот часть кода, с которой я работал:

public class ActiveTasks
    {
        //Properties here
    }

public List<ActiveTasks> ActTaskList = new List<ActiveTasks>();

for (int i = 0; i < ListActive.Items.Count; i++)
        {
            if (DTime.Date == newDateTime.Date)
            {
                if (newDateTimeLeft.CompareTo(TimeSpan.Zero) <= 0 && ActTaskList[i].ActReminded != "true")
                {
                    MessageBox.Show("!!!!");
                    ActTaskList.Add(new ActiveTasks()
                    {
                        ActTitle = ActTaskList[i].ActTitle,
                        ActDesc = ActTaskList[i].ActDesc,
                        ActDate = ActTaskList[i].ActDate,
                        ActTime = ActTaskList[i].ActTime,
                        ActStatus = ActTaskList[i].ActStatus,
                        ActReminded = "true",
                        ActRepeat = ActTaskList[i].ActRepeat
                    });

                    ListActive.Items.RemoveAt(i);

                    ActTaskList.RemoveAt(i);

                    XDocument XmlActTasks = GenerateActiveListToXML(ActTaskList);
                }
            }
        }

Я действительно решил, что, возможно, захочу сохранить статус напоминания, независимо от того, был он показан или нет, поскольку я не хотел бы повторять напоминание каждый раз при открытии программы. Поскольку я не знаю, как обновить отдельную часть ActTaskList, я просто добавил ее заново, а затем удалил оригинал. Этот код распознает, что если это произойдет, он изменит состояние напоминания с ложного на истинное; после того, как я ок'едил весь спам. Так что он остановит MessageBox, как только мне удастся закрыть все окна сообщений. Тем не менее, это не останавливает спам. Будет ли это связано с тем, что я установил таймер на 100 мс? Или они могут быть альтернативным способом заставить окно сообщения появиться, не находясь в таймере?

Ответы [ 3 ]

1 голос
/ 02 апреля 2012

Шансы текущего времени, точно совпадающие с точностью до секунды, что происходит в вашем цикле, невелики.Почему бы не рассматривать newDateTime как точку отсечения и просто установить флаг?

//Declare this outside of the loop
bool hasDisplayed = false;

//Inside the timer event handler
if (!hasDisplayed && DateTime.Now >= newDateTime)
{
    hasDisplayed = true;

    MessageBox.Show("!!!!!!!!!!!!!");
}
0 голосов
/ 02 апреля 2012

Вы говорите, что уже пробовали логическое значение, указывающее, что сообщение уже было показано, я предполагаю, потому что код, вероятно, выглядел так, как показано ниже.

void TimerLoop()
{
    bool msgAlreadyShown;

    if(!msgAlreadyShown)
    {
        MessageBox.Show("!!!!!!!");
    }
    // Other work in your timer function
}

Проблема с этим кодом заключается в том, чтоbool будет установлен в false каждый раз, когда функция вызывается таймером.Вы не опубликовали много кода, но вы, по крайней мере, указали, что пытаетесь выполнить, таймер, который проверяет, нужно ли пользователю представлять напоминание.

Я собираюсь сделать несколькодикие предположения о том, как вы собрали свое программное обеспечение, есть большая вероятность, что оно далеко, но я надеюсь, что оно может указать вам верное направление.У вас может быть некоторый класс напоминаний, подобный этому:

public class Reminder
{
    string Message { get; set;}
    DateTime Alarm { get; set; } 
    bool IsDismissed { get; set; }
}

Я предполагаю, что вы можете захотеть иметь несколько напоминаний, которые можно проверять в цикле таймера, чтобы ваш цикл таймера мог выглядеть примерно так:

private List<Reminder> _activeReminders; // A list of reminders

void TimerLoop(object s, ElapsedEventArgs e)
{
    lock(_activeReminders) 
    {
        var now = DateTime.Now;
        foreach(var reminder in _activeReminders)
        {
            // only run this code if the time has passed and it hasn't already
            // been shown
            if(now.CompareTo(reminder.Alarm) >= 0 && !reminder.IsDismissed)
            {
                MessageBox.Show(reminder.Message);
                reminder.IsDismissed = true;
            }
        }
    }
}

Это довольно наивная реализация, так как вы, вероятно, не хотите навсегда удерживать напоминания, и напоминания никогда не удаляются из списка _activeReminders, но по сути вам просто нужно добавитькакое-то состояние, чтобы определить, было ли уже показано напоминание.

Конечно, это также не полный пример, так как я никогда не обновляю поле _activeReminders и не добавляю к нему что-либо, но я думаю, что это может помочь понять, что вам нужно сделать через,Кроме того, вы можете не заботиться о множественных напоминаниях, и ваш код таймера может выглядеть совсем не так.Основная идея состояла в том, чтобы показать вам, как вы можете отслеживать состояние напоминания и адаптировать его к своему собственному коду.Вышесказанное было просто примером.

Кроме того, я на самом деле не проверял его, поэтому относился к нему больше как к псевдокоду, чем к чему-либо еще.Однако логика логична и должна вызывать появление окна сообщения только один раз.

0 голосов
/ 02 апреля 2012

Можете ли вы сделать что-то подобное?

Action message = () => MessageBox.Show("!!!!!!!!!!!!!"));
object lockOb = new object();

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    lock(lockOb)
        if(null != message)
        {
            message();
            message = null;
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...