所以我基本上是在质疑到目前为止我所学到的有关C#垃圾收集的一切。
我有一个名为User
的类,User
具有2个属性(system.Timers)Timer
和名称属性,每次创建User
时我绑定一个事件,该事件包括每0.5秒将事件和事件通知日志。
问题是,每次我将事件绑定到User
时,即使我将其从列表中删除,垃圾回收器似乎也似乎并没有处置该类。
User
课程
public class User
{
/// <summary>
/// A specific name that I give to created users so I know which one was created/destroyed
/// </summary>
public string Name { get; set; }
/// <summary>
/// A timer that fires an event every so often
/// </summary>
public Timer _timer;
public User(string name)
{
Name = name;
// Initializing the Timer
// Here is where it get interesting when I initialize the Timer class this user class just doesn't get disposed
// even if I set "Enabled" to false
_timer = new Timer()
{
AutoReset = true,
Enabled = true,
Interval = TimeSpan.FromSeconds(0.5).TotalMilliseconds,
};
// Notifying console that user has been created
IoC.Log().WriteLine($"\n{Name} was created\n");
// Bind the event
// I've attempted to bind the event as lambada function and as a
// "normal" function both seem to be causing the "error"
//_timer.Elapsed += (sender, e) => IoC.Log().WriteLine($"{Name} elapsed");
}
/*
private void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
// Notify that an event has been called
IoC.Log().WriteLine($"{Name} elapsed");
}*/
~User()
{
// Notify that user has been destroyed/disposed
IoC.Log().WriteLine($"\n{Name} destroyed <---------- \n");
}
}
UserList
类
public class UserList
{
private ObservableCollection<User> _user = new ObservableCollection<User>();
/// <summary>
/// Stores a list of users
/// </summary>
public ObservableCollection<User> Users
{
get => _user;
set => _user = value;
}
public UserList()
{
Users.CollectionChanged += Users_CollectionChanged;
}
private void Users_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// When a user is added to the list
if (e.Action == NotifyCollectionChangedAction.Add)
{
// Get the new user
User addedUser = Users[e.NewStartingIndex];
// Bind an Elapsed event to the user's timer
addedUser._timer.Elapsed += (_sender, _e) => IoC.Log().WriteLine($"{addedUser.Name} elapsed");
};
}
}
呼叫班
受保护的覆盖异步无效OnStartup(StartupEventArgs e) { //设置DI(将ninject与对UserList类的常量绑定用作测试) IoC.Setup();
// Initialize a window
MainWindow = new MainWindow();
MainWindow.Show();
// Create a scoped user
// Should be destoryed as soon as we get out of scope
// Does actaully get disposed (because I am not binding an event ?)
{
User user = new User("user");
};
// Adding user as a new instance
IoC.Get<UserList>().Users.Add(new User("New User1"));
IoC.Get<UserList>().Users.Add(new User("New user2"));
// Creating user as a reference
User user1 = new User("user1");
User user2 = new User("user2");
// Adding the "reference" userlist
IoC.Get<UserList>().Users.Add(user1);
IoC.Get<UserList>().Users.Add(user2);
// Notify that we are deleting users
IoC.Log().WriteLine("\nWaiting 5 seconds\n");
await Task.Delay(3000);
IoC.Log().WriteLine("\nDeleting users..\n");
// Removing created users
IoC.Get<UserList>().Users.RemoveAt(3);
IoC.Get<UserList>().Users.RemoveAt(2);
IoC.Get<UserList>().Users.RemoveAt(1);
IoC.Get<UserList>().Users.RemoveAt(0);
// NOtify that we finished
IoC.Log().WriteLine("\nFinised deleting\n");
// And after a while the Garbage collector should dispose of the references
return;
这是到目前为止我尝试过的事情:
在调用类中创建一个与ElapsedEvent
相同的事件,并在创建User
对象时绑定该事件
当我要处置User
对象时,我取消绑定该事件
呼叫班
// Not binding any event to the user's that will be added to the list
// This works fine they are disposed like intended
//But this scoped user appears to not be disposed
User user;
{
user = new User("user");
user._timer.Elapsed += _timer_Elapsed;
};
// Logic that takes a while
// So we can see the event in action
await Task.Delay(3000)
// Unbind event.
// But 'user' is still not being disposed even after existing scope
user._timer.Elapsed -= _timer_Elapsed;
试图将事件绑定到UserList类中。这没有用,因为当我调用'CollectionChanged'时,我无权访问已删除的用户,并且无法取消绑定该事件
UserList
类
private void Users_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// When a user is added to the list
if (e.Action == NotifyCollectionChangedAction.Add)
{
// Get the new user
User addedUser = Users[e.NewStartingIndex];
/ Bind an Elapsed event to the user's timer
// This works because I have access to the newly created/added user
//addedUser._timer.Elapsed += (_sender, _e) => IoC.Log().WriteLine($"{addedUser.Name} elapsed");
};
}
// If a user is removed from the list
else
{
// After all user's have been removed this throws an OutOfRangeException, Furthermore I never have acces to the CURRENT user that was removed
User addedUser = Users[e.OldStartingIndex];
};