Looking at the LIT source, I'm not seeing any reason why Disposing it would cause any issue. Dispose looks like this:
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;
}
}
}
As you can see, it sets Enabled to false
and then sets a WaitHandle
.
The Enabled implementation is similarly simple:
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);
}
}
}
}
Basically if we're disabling and we were enabled, the same WaitHandle that Dispose will be setting is getting set. Redundant, yes, but not a problem. SetEvent is not a clocking call, so this code is all that happens as a direct result of your call and should be the only thing that would affect a "hang" scenario. But for completeness, let's look at what this event is triggering. Here's teh worker thread proc (which is largely the meat of the LIT class):
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();
}
}
}
About half way in you'll see a source = WaitAny
call, which is where that event is caught. It simply returns 1
when the event from the above snipptes is called, which drops us to the else
which sets m_enabled to false, which then exits the while loop and runs the finally block. The finally block resets the waithandle is all threads have exited and you're done. Again, pretty simple, and I see no potentials for a hang.
At this point all I can recommend is putting Debug.Writeline
calls into the LIT source to see what's happening in your use case. It might shed a little more light on what's happening in your environment to cause bad behavior.
Bear in mind that Disposing the LIT still may leave a single notification active in your OS notifications queue, so the event registered is still going to fire one more time. That still should have zero impact, as we're no longer listening for it so it's just going to fire with no listeners, which is not a problem.