首页 > 解决方案 > C# WPF 在单击重复操作时出现气球提示问题

问题描述

我可能错过了显而易见的事情,请耐心等待,因为我正在学习这个版本,但是我有一个 WPF 应用程序的问题,它使用气球提示来通知用户事件,然后他们单击气球提示来打开一个窗口,向他们提供更多信息。这工作正常,但我们需要多线程气球提示,以便一次显示多个,这就是我们遇到问题的时候。

显示第一个气球提示,单击它时,我们可以正确打开窗口,关闭窗口,一切正常。当第二个气球提示显示并被单击时,它会生成 2 个新窗口,第三个会生成 3 个,依此类推。

为简单起见,我们测试的两个事件是由对象设置的计时器。我将贯穿整个过程,因为我不确定我们的问题在哪里。

对象定义如下:-

public class Item
    {
        public string ItemID { get; set; }
        public string ItemName { get; set; }
        public string ItemText { get; set; }
        public string ConfigValue { get; set; }
    }

我们有 2 个项目集,我们将它们添加到一个名为 repeatItems 的列表中:-

Item1 (ItemID = "1", ItemName = "Item1", ItemText = "Test text for item1", ConfigValue = "1")
Item2 (ItemID = "2", ItemName = "Item2", ItemText = "Test text for item2", ConfigValue = "2")

然后我们使用任务工厂允许我们设置 2 个单独的计时器:-

//Create Task Factory to handle Repeat Items
var repTaskFactory = new TaskFactory();

//Create Thread for Repeat Items
foreach (Item item in repeatItems)
{
    repTaskFactory.StartNew(() => RepItem(item));
}

RepItem 函数定义如下:-

//Function to handle Repeat Items
        public async void RepItem(Item item)
        {
            //Create a new custom timer
            var repTimer = new CustomTimer();

            //assign Item details to the timer
            repTimer.item = item;

            //create and set the timer time value as confiog value is in Minutes
            var mil = Int32.Parse(nudge.ConfigValue) * 60 * 1000;
            repTimer.Interval = mil;

            //set the response for the timer ending
            repTimer.Elapsed += ItemAction;

            //cause timer to autorepeat
            repTimer.AutoReset = true;

            //Start the timer
            repTimer.Enabled = true;
        }

调用的 CustomTimer 设置如下,以允许它为以后的调用携带附加信息:-

class CustomTimer : System.Timers.Timer
    {
        public Item item;
    }

动作函数是:-

public void ItemAction(Object source, ElapsedEventArgs e)
        {
            //Create ability to multi thread allowing multiple balloon tips to be displayed
            var balloonTaskFactory = new TaskFactory();
            
            //Get details from the sending time
            CustomTimer timer = (CustomTimer)source;

            //Get Item from the timer type
            Item item = new Item();
            item = timer.item;

            //Create new thread and show ballon tip
            balloonTaskFactory.StartNew(() => CreateItemBalloonTip(item));         
        }

最后我们创建并显示气球提示:-

public void CreateItemBalloonTip(Item item)
        {
            //Set details of Balloon Tip
            m_notifyIcon.BalloonTipText = item.ItemText;
            m_notifyIcon.BalloonTipTitle = item.ItemName;
            m_notifyIcon.BalloonTipClicked += new EventHandler(ItemBalloonTipClicked);

            m_notifyIcon.ShowBalloonTip(2000);
        }

ItemBalloonTipClicked 相当简单,因为它会打开一个新窗口并将 item.ItemName 传递给它:-

public void ItemBalloonTipClicked(Object sender, EventArgs e)
        {
            NotifyIcon cust = (NotifyIcon)sender;

            string item = cust.BalloonTipTitle;
            Window1 win2 = new Window1(item);
            win2.Show();
        }

在某个地方我猜 BalloonTipClicked 的监听器没有关闭并且一遍又一遍地射击?我该如何处理这个问题?

提前致谢。

标签: c#wpfmultithreading

解决方案


尝试将事件处理程序注销到BalloonTipClicked单击事件处理程序中的事件:

public void ItemBalloonTipClicked(Object sender, EventArgs e)
{
    NotifyIcon cust = (NotifyIcon)sender;
    cust.BalloonTipClicked -= ItemBalloonTipClicked; // <--

    string item = cust.BalloonTipTitle;
    Window1 win2 = new Window1(item);
    win2.Show();
}

推荐阅读