C# 事件处理程序未及时删除
C# event handler not removed in a timely manner
我有一个 Windows 基于表单的 C# 项目,其表单具有大约 30-50 个字段(文本、组合框等)。我使用一个函数为所有对象添加相同的事件处理函数:
private readonly EventHandler hProjectBecameModified;
hProjectBecameModified = new EventHandler(ProjectBecameModified);
private void AddEventHandlers()
{
RemoveEventHandlers();
foreach (var _list in new List<TableLayoutControlCollection> {
tableLayoutPanelGeneral.Controls,
tableLayoutPanelReverse.Controls,
tableLayoutPanelBuild.Controls,
tableLayoutPanelLocalization.Controls,
})
{
foreach (var control in _list)
{
if (control.GetType() == typeof(ComboBox))
(control as ComboBox).SelectedIndexChanged += hProjectBecameModified;
else if (control.GetType() == typeof(CheckBox))
(control as CheckBox).CheckedChanged += hProjectBecameModified;
else if (control.GetType() == typeof(TextBox))
(control as TextBox).TextChanged += hProjectBecameModified;
}
}
}
private void ProjectBecameModified(object sender, EventArgs e)
{
m_isSelectedProjectToBeSaved = true;
//Etc, user modified the stuff and it is to be saved
}
并且有一个 RemoveEventHandlers() 函数与 -=s 而不是 +=s 相同。请注意,我使用条件断点检查了该函数是否适用于实际控件,因此应删除处理程序。
当我以编程方式设置内容时,我会这样做:
RemoveEventHandlers();
//setting stuff, like
//textBoxManufacturer.Text = m_selectedProject.Manufacturer;
AddEventHandlers();
问题是对于某个组合框,这是行不通的:
RemoveEventHandlers();
comboBoxConfiguration.SelectedIndex = something;
将触发事件处理函数。 (请注意,它有另一个事件处理程序,有自己的 RemoveEventHandlers() 和 AddEventHandlers() )
但是,如果我写:
comboBoxConfiguration.SelectedIndexChanged -= hProjectBecameModified;
comboBoxConfiguration.SelectedIndex = something;
RemoveEventHandlers();
会起作用。 (但如果我添加更多 RemoveEventHandlers() 调用将不起作用)。
虽然实际代码现在有效,但我对它的实际工作及其原因感到担忧。
- 这是一个糟糕的设计吗?
- 不知何故这是一种赛车条件,即。 RemoveEventHandlers() 可能 运行 在不同的线程上并且没有及时删除事件处理程序? (会很奇怪)。
- 是否可以多次添加相同的事件处理程序从而导致问题? (不太可能)。
- (提供的信息够吗?)
PS 请注意,在第一条评论之后,我在 AddEventHandlers() 函数的第一行添加了 RemoveEventHandlers() 调用。
我会建议一个更简单的选项。
试试这个:
private bool _suspended = false;
void Suspend()
{
_suspended = true;
}
void Resume()
{
_suspended = false;
}
private void ProjectBecameModified(object sender, EventArgs e)
{
if (!_suspended)
{
m_isSelectedProjectToBeSaved = true;
//Etc, user modified the stuff and it is to be saved
}
}
您根本不需要通过这种方式删除事件处理程序。
我有一个 Windows 基于表单的 C# 项目,其表单具有大约 30-50 个字段(文本、组合框等)。我使用一个函数为所有对象添加相同的事件处理函数:
private readonly EventHandler hProjectBecameModified;
hProjectBecameModified = new EventHandler(ProjectBecameModified);
private void AddEventHandlers()
{
RemoveEventHandlers();
foreach (var _list in new List<TableLayoutControlCollection> {
tableLayoutPanelGeneral.Controls,
tableLayoutPanelReverse.Controls,
tableLayoutPanelBuild.Controls,
tableLayoutPanelLocalization.Controls,
})
{
foreach (var control in _list)
{
if (control.GetType() == typeof(ComboBox))
(control as ComboBox).SelectedIndexChanged += hProjectBecameModified;
else if (control.GetType() == typeof(CheckBox))
(control as CheckBox).CheckedChanged += hProjectBecameModified;
else if (control.GetType() == typeof(TextBox))
(control as TextBox).TextChanged += hProjectBecameModified;
}
}
}
private void ProjectBecameModified(object sender, EventArgs e)
{
m_isSelectedProjectToBeSaved = true;
//Etc, user modified the stuff and it is to be saved
}
并且有一个 RemoveEventHandlers() 函数与 -=s 而不是 +=s 相同。请注意,我使用条件断点检查了该函数是否适用于实际控件,因此应删除处理程序。
当我以编程方式设置内容时,我会这样做:
RemoveEventHandlers();
//setting stuff, like
//textBoxManufacturer.Text = m_selectedProject.Manufacturer;
AddEventHandlers();
问题是对于某个组合框,这是行不通的:
RemoveEventHandlers();
comboBoxConfiguration.SelectedIndex = something;
将触发事件处理函数。 (请注意,它有另一个事件处理程序,有自己的 RemoveEventHandlers() 和 AddEventHandlers() )
但是,如果我写:
comboBoxConfiguration.SelectedIndexChanged -= hProjectBecameModified;
comboBoxConfiguration.SelectedIndex = something;
RemoveEventHandlers();
会起作用。 (但如果我添加更多 RemoveEventHandlers() 调用将不起作用)。
虽然实际代码现在有效,但我对它的实际工作及其原因感到担忧。
- 这是一个糟糕的设计吗?
- 不知何故这是一种赛车条件,即。 RemoveEventHandlers() 可能 运行 在不同的线程上并且没有及时删除事件处理程序? (会很奇怪)。
- 是否可以多次添加相同的事件处理程序从而导致问题? (不太可能)。
- (提供的信息够吗?)
PS 请注意,在第一条评论之后,我在 AddEventHandlers() 函数的第一行添加了 RemoveEventHandlers() 调用。
我会建议一个更简单的选项。
试试这个:
private bool _suspended = false;
void Suspend()
{
_suspended = true;
}
void Resume()
{
_suspended = false;
}
private void ProjectBecameModified(object sender, EventArgs e)
{
if (!_suspended)
{
m_isSelectedProjectToBeSaved = true;
//Etc, user modified the stuff and it is to be saved
}
}
您根本不需要通过这种方式删除事件处理程序。