Глядя на источник LIT, я не вижу никакой причины, по которой его удаление может вызвать проблемы.Dispose выглядит следующим образом:
public void Dispose()
{
lock (m_interlock)
{
m_disposing = true;
if (Enabled)
{
Enabled = false;
}
if (m_quitHandle != null)
{
m_quitHandle.Set();
m_quitHandle.Close();
m_quitHandle = null;
}
}
}
Как видите, для параметра Enabled установлено значение false
, а затем для WaitHandle
.
Реализация Enabled аналогично проста:
public bool Enabled
{
get { return m_enabled; }
set
{
lock (m_interlock)
{
m_cachedEnabled = value;
if ((m_enabled && value) || (!m_enabled && !value))
{
return;
}
m_enabled = value;
// force any existing waiting threads to exit
if(ThreadCount > 0)
{
m_quitHandle.Set();
Thread.Sleep(1);
}
if (m_enabled)
{
// start the wait thread
ThreadPool.QueueUserWorkItem(InternalThreadProc);
}
}
}
}
В основном, если мы отключаем, и мы были включены, устанавливается тот же WaitHandle, который будет устанавливать Dispose.Избыточный, да, но не проблема.SetEvent не является синхронизирующим вызовом, поэтому этот код - все, что происходит как прямой результат вашего вызова, и должен быть единственным, что может повлиять на сценарий «зависания».Но для полноты давайте посмотрим, что вызывает это событие.Вот рабочий процесс рабочего потока (который в основном является мясом класса LIT):
private void InternalThreadProc(object state)
{
ThreadCount++;
int source;
string eventName = Guid.NewGuid().ToString();
EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
try
{
while (m_enabled)
{
if (m_disposing) return;
if (m_useFirstTime)
{
Notify.RunAppAtTime(string.Format(@"\\.\Notifications\NamedEvents\{0}",
eventName), m_firstTime);
m_useFirstTime = false;
}
else
{
// set up the next event
Notify.RunAppAtTime(string.Format(@"\\.\Notifications\NamedEvents\{0}",
eventName), DateTime.Now.Add(m_interval));
m_firstTime = DateTime.MinValue;
}
if (m_disposing) return;
source = OpenNETCF.Threading.EventWaitHandle.WaitAny(new WaitHandle[]
{ waitHandle, m_quitHandle });
// see if it's the event
if (source == 0)
{
m_cachedEnabled = null;
// fire the event if we have a listener
if (Tick != null)
{
// we need to decouple this call from the current thread
// or the lock will do nothing
ThreadPool.QueueUserWorkItem(new WaitCallback(
delegate
{
Tick(this, null);
}));
}
if (OneShot)
{
if (m_cachedEnabled != null)
{
m_enabled = (m_cachedEnabled == true);
}
else
{
m_enabled = false;
}
}
}
else
{
m_enabled = false;
}
}
}
finally
{
waitHandle.Close();
ThreadCount--;
if (ThreadCount == 0)
{
m_quitHandle.Reset();
}
}
}
Примерно на половине пути вы увидите вызов source = WaitAny
, в котором и происходит это событие.Он просто возвращает 1
, когда вызывается событие из вышеприведенных фрагментов, что приводит нас к else
, который устанавливает m_enabled в false, который затем выходит из цикла while и запускает блок finally.Блок finally сбрасывает дескриптор ожидания, если все потоки вышли, и все готово.Опять же, довольно просто, и я не вижу потенциальных возможностей для зависания.
На данный момент все, что я могу порекомендовать, это поместить вызовы Debug.Writeline
в источник LIT, чтобы увидеть, что происходит в вашем случае использования.Это может пролить немного больше света на то, что происходит в вашей среде, и вызвать плохое поведение.
Имейте в виду, что при удалении LIT все еще может оставаться активным одно уведомление в очереди уведомлений ОС, поэтому зарегистрированное событие по-прежнемусобираюсь уволить еще раз.Это по-прежнему должно иметь нулевой эффект, так как мы больше не слушаем его, так что оно просто сработает без слушателей, что не проблема.