2010-02-19 78 views
1

當運行我的程序時,有時我會得到這些異常,其他時候我不會。這是執行流程:System.InvalidOperationException和System.Reflection.TargetInvocationException偶爾發生

用戶單擊Window1類中的按鈕。
類收集輸入,backgroundWorker.RunWorkerAsync()已啓動。
在DoWork中,調用App.doStuff()。
內App.doStuff(),我創建另一個線程來顯示進度在不同的窗口是這樣的:)

Thread newWindowThread = new Thread(new ThreadStart(showProgressMethod)); 
newWindowThread.SetApartmentState(ApartmentState.STA); 
newWindowThread.IsBackground = true; 
newWindowThread.Start(); 

在showProgressMethod(,我做的:現在

progressWindow = new MyProgressWindow(this); 
progressWindow.Show(); 
System.Windows.Threading.Dispatcher.Run(); 

,如果我第一次運行它,我從來沒有任何問題。但是,如果我在完成操作後重做該操作,那麼我可能會得到例外。看看代碼,通過調用dispatcher.Run()和Thread.Start(),我感覺到我做錯了什麼,但是我不太瞭解線程模型,所以我是不確定。

無論哪種方式,在第一次運行時,程序從不做任何異常。但有時當我再次單擊該按鈕以激活該過程時,發生異常。我覺得當程序沒有足夠的時間清理時會發生?雖然我不確定。

編輯

看來這個問題是ProgressWindow線程不會結束。顯然,在ProgressWindow內部的App.doStuff()或Dispatcher.Thread.Abort()中添加一個Thread.Abort()可以修復問題。顯然。

但是,由於Abort()方法,它仍然引發異常,儘管它不再崩潰。我也不明白爲什麼關閉ProgressWindow不會結束線程。從我讀過的使用Thread.Abort()不是很好的做法,雖然我不明白爲什麼。

EDIT 2

Thread.Abort的仍然保留着它有時崩潰。所以,我所做的就是:
更換Show()呼籲ShowDialog(),作爲建議和
取出呼籲System.Windows.Threading.Dispatcher.Run();

回答

0

裏面是什麼MyProgressWindow?也許它會從第一個newWindowThread一次訪問一次ResourceDictionary兩次,一次從第二次? ResourceDictionary s不能在兩個線程之間共享。

+0

ProgressWindow僅具有對mainWindow.backgroundWorker的引用。 ProgressWindow中的關閉事件調用backgroundWorker.CancelAsync() - 如果關閉ProgressWindow,則取消該任務。我評論說,這些線路阻止它做任何事情,並沒有這樣做。 – zxcvbnm 2010-02-19 19:24:31

0

a)TargetInvocationException將在InnerException屬性中出現真正的異常 - 請檢查該異常。

b)你確定你沒有重複使用/觸摸來自兩個不同線程的對象嗎?如果WPF檢測到從一個線程訪問的依賴項屬性,則它會顯式拋出它,該線程不是創建它的依賴屬性。

+0

好吧,當進度窗口關閉時,我啓用主窗口,當backgroundworker線程結束時,關閉進度窗口。所以我正在訪問其他線程資源,但我打電話給調度員,並使用BeginInvoke,所以我認爲我是這樣做的正確方法。 – zxcvbnm 2010-02-20 15:27:57

+0

是的,這是正確的方式。但要確保你有合適的調度員。 – 2010-02-21 03:57:35

0

用戶單擊Window1類中的按鈕。 類收集輸入,backgroundWorker.RunWorkerAsync()已啓動。 在DoWork中,調用App.doStuff()。 內App.doStuff(),我好,你現在的代碼在UI線程上運行時創建另一個線程來顯示進度...

,BackgroundWorker的線程上運行的代碼,並在新的運行代碼,第三個線程,一個不是UI線程,這是更新UI元素。我有這個權利嗎?因爲這聽起來像是幾乎肯定是一個問題。

編輯:

我很驚訝,你在做什麼工作可言,而不是它的工作原理不一致。

BackgroundWorkerProgressChanged事件是您希望用於在後臺運行的方法和用戶界面之間進行互操作的方式。它在UI線程上運行。

+0

是的,這就是我正在做的事情。第三個線程中的代碼控制是否啓用該窗口 - 如果進度條處於活動狀態,則禁用該窗口以防止用戶多次啓動該進程。那麼我該如何去做呢? – zxcvbnm 2010-02-20 15:25:50

+0

我已經使用progresschanged更新進度窗口中的進度條。但我仍然需要創建第三個線程才能顯示進度窗口。我認爲。也許有一種方法可以在ui使用的同一個線程中創建進度窗口,然後用backgroundworker做數學運算,但我不知道。 – zxcvbnm 2010-02-20 19:59:33

+0

您可以只使用Window.Show(),它將通過調度程序進行泵送。這不是一個阻塞的電話。然而,ShowDialog()是。 – 2010-02-21 03:58:48

相關問題