查看 LIT 源代码,我看不出有任何理由说明 Disposing 它会导致任何问题。处置看起来像这样:
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
,然后设置 a 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);
}
}
}
}
基本上,如果我们禁用并启用,则 Dispose 将设置的相同 WaitHandle 将被设置。冗余,是的,但不是问题。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 仍可能会在您的操作系统通知队列中留下一个处于活动状态的通知,因此注册的事件仍将再次触发一次。这仍然应该是零影响,因为我们不再监听它,所以它只会在没有听众的情况下触发,这不是问题。