軟件第一次能夠正常運行,可是第二次只在任務管理器的進程菜單中出現應用程序的進程名稱,並且主界面也沒法顯示。編程
這個問題至關詭異,以致於開始的很長時間裏不知道問題出在哪。在win7測試機上具體表現爲:雙擊軟件快捷方式後第1次界面能夠顯示,若是退出軟件再啓動時就沒有任何反應,再次雙擊圖標彈出重複運行警告。由於代碼作了重複運行檢測,說明程序已經運行,可是界面呢?爲何沒有界面?也沒有異常提示。打開任務管理器,程序集名稱安靜的在進程列表裏躺着,歲月靜好。真是見鬼了,手動幹掉進程,再來。依然如此,沒有任何界面。在本身的開發機上運行一切正常,主界面正常顯示,更新提示能夠正常彈出。在另外的一臺win7和win8機器上這個問題時有時無。安全
沒辦法,首先百度。還真有人碰到相似的問題,任務管理器裏有進程,界面不顯示。認真看了一下他的問題描述及解決辦法,緣由是在界面構造函數調用初始化函數時,目標機器上沒有對應字體,形成控件渲染不下去,程序直接停在那裏。對照他的解決辦法對本身程序的控件初始化函數進行單步調試,一切正常,沒有問題。並且,個人問題是界面有時能夠出現,有時沒法出現,因此應該不是界面初始化的問題。雖然這個答案對我解決問題沒有幫助,可是貼主解決問題的思路值得學習,並且他程序有完整的日誌功能,能夠幫助分析解決問題,而個人程序根本沒有日誌功能。異步
在開發機上調試運行時,功能正常,可是會出現System.InvalidOperationException類型的異常,提示線程間操做無效,從不是建立控件「FrmUkeMain」的線程訪問它。解釋一下,「FrmUkeMain」是個人主界面類,在主界面的Load事件中,使用了一個委託的BeginInvoke函數異步執行檢查是否有可用的版本更新,使用回調函數的方式來顯示結果,若是能夠更新就彈出一個提示更新的窗口。由於使用MessageBox顯示有時會被主界面擋住,用戶稍不注意就看不見這個更新提示。因此我把這個提示作成了一個窗口,而後以showDialog的方式顯示出來。通常狀況下,若是窗口以showDialog的方式顯示,會阻止調用窗口的消息響應,只有彈出窗口結束,調用窗口才能繼續工做。只是這一次,雖然提示窗口顯示正常顯示出來,可是主窗口依然能夠繼續響應消息。(真是見鬼了,我當時壓根沒注意到彈出窗口和主窗口根本不在一個線程。)若是主窗口能夠繼續響應,那麼彈出窗口仍然可能會被阻擋,問題依然存在。查看幫助文檔發現showDialog還有一個重載方法,能夠「將窗體顯示爲具備指定全部者的模式對話框」,這個方法也許管用。而後我就將主窗口的this引用傳給了showDialog方法,再次運行達到預期效果。只是在調試時總會出現一開始所說的異常,而後我又按照網上的方式這個把窗體的CheckForIllegalCrossThreadCalls屬性改成false,這樣就不會用這個出現這個異常了。這裏提示一下,正是從傳this引用到關閉跨線程調用的異常檢查這一系列的動做,才形成了後面的問題。因此說,有異常就要完全解決,不要使用這種掩耳盜鈴的解決方法。函數
好了,在開發機上這一套動做下來,沒有異常了,功能運行也正常,一切看似很完美。可是,在測試機器上界面時有時無。何解?在開發機上調試也沒有什麼眉目。最後沒辦法,索性把項目文件放到測試機器上調試。將斷點設置在showDialog(this)調用的位置,而後單步執行。主界面能夠彈出,可是一片空白,沒有控件顯示,也沒有異常出現。來來回回試了幾回都是這樣,也沒找到問題緣由。最後索性不打斷點,直接F5啓動,跟以前同樣窗口無顯示,沒有任何東西出現,就好像程序沒有運行同樣,可是任務管理器有承載進程。就這樣等了一會,而後彈出這個下面這個窗口:學習
「上下文切換死鎖」,這是什麼鬼?對CLR運行機制不太瞭解,可是隱隱感受到應該是異步調用出了問題。先把異步調用代碼註釋掉,再次運行,窗口能夠正常顯示,除更新意外的其餘功能正常,因此問題就位於異步調用代碼中。異步調用代碼中可能引發死鎖的應該就是那個主窗口的this引用,把this引用去掉,而後開啓異步功能。此次主窗口能夠正常顯示,除了更新提示窗口可能被遮擋外功能都正常。看來這個主窗口的this引用就是引發死鎖的元兇了。至於爲何會引發死鎖,應該和我在窗體的Load事件中使用異步並傳入主窗體的this引用有關。其實以前編程中遇到控件跨線程調用,在調試時報異常,可是運行的時候通常能夠正常運行,因此一開始也沒當回事。如今算是給個提醒了,仍是不要跨線程調用,非要在跨線程調用的話仍是使用安全的方式,好比委託。測試
好了,既然問題找到了,那就想辦法解決。不使用委託的BeginInvoke方法來實現異步檢查更新,改用BackgroudWorker類來實現,這樣就不存在跨線程調用主線程控件的問題了。字體
PS:在出現ContextSwitchDeadlock這個問題的時候,我在百度經驗上看到一個解決辦法是——將「調試」異常設置裏的「ContextSwitchDeallock」這個異常引起設置選項不選中。呃。。。這真是一個眼不見心不煩的解決辦法。這讓我想到那句話:既然咱們沒法解決問題,那麼咱們就解決提出問題的人。this