LITソースを見ると、それを破棄すると問題が発生する理由はわかりません。廃棄は次のようになります。
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;
}
}
}
ご覧のとおり、[有効]をに設定してから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);
}
}
}
}
基本的に、無効にして有効にした場合、Disposeが設定するのと同じWaitHandleが設定されます。冗長です、はい、しかし問題ではありません。SetEventはクロッキング呼び出しではないため、このコードは呼び出しの直接の結果として発生するすべてであり、「ハング」シナリオに影響を与える唯一のものである必要があります。ただし、完全を期すために、このイベントがトリガーしているものを見てみましょう。ワーカースレッドproc(主に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ブロックを実行します。最後に、ブロックは待機ハンドルをリセットします。すべてのスレッドが終了し、完了です。繰り返しになりますが、非常に単純で、ハングアップの可能性はありません。
この時点で私がお勧めできるのはDebug.Writeline
、LITソースに呼び出しを入れて、ユースケースで何が起こっているかを確認することだけです。それは悪い行動を引き起こすためにあなたの環境で何が起こっているかについてもう少し光を当てるかもしれません。
LITを破棄すると、OS通知キューで1つの通知がアクティブのままになる可能性があるため、登録されたイベントは引き続き1回発生することに注意してください。私たちはもはやそれを聞いていないので、それでも影響はゼロであるはずです。したがって、リスナーなしで起動するだけです。これは問題ではありません。