7

我真的不明白這個錯誤是如何發生在這段代碼上的。請檢查代碼自己試圖讀取或寫入受保護的內存。這通常表明其他內存已損壞

void dispatcherTimer_Tick(object sender, EventArgs e) 
{ 
    string srUrl = lstLocalIndex[irLocalIndex] + lstMainIndex[irMainIndex].Replace("0;",""); 

    Task.Factory.StartNew(() => 
    { 
     startNewWindow(srUrl); 
    }); 

} 


    void startNewWindow(string srUrl) 
{ 
    NewWindowThread<TitleWindow, string>(c => new TitleWindow(c), srUrl); 
} 

下面這段代碼是在錯誤發生。我也將附上截圖

 private void NewWindowThread<T, P>(Func<P, T> constructor, P param) where T : Window 
    { 
     Thread thread = new Thread(() => 
     { 
      T w = constructor(param); 
      w.Show(); 
      w.Closed += (sender, e) => w.Dispatcher.InvokeShutdown(); 
      try 
      { 
       System.Windows.Threading.Dispatcher.Run(); 
      } 
      catch 
      { 

      } 
     }); 
     thread.SetApartmentState(ApartmentState.STA); 
     try 
     { 
      thread.Start(); 
     } 
     catch 
     { 

     } 
    } 

此錯誤會導致整個軟件拋出錯誤而停止工作,即使我打電話他們在新的線程:(

此行拋出錯誤System.Windows.Threading.Dispatcher。運行();

請檢查還截圖

enter image description here

C#4.0 WPF

+0

實際上,您使用*兩個*線程,即Task中的線程,然後是Thread線程,最好將您想要作爲啓動代碼運行的代碼放在Thread中。 – casperOne 2012-04-02 19:40:19

+0

@casperOne我也試過這個應用程序崩潰。過了一段時間後,這種情況不會立即發生。它運行30分鐘然後崩潰。崩潰時間改變。 – MonsterMMORPG 2012-04-02 19:41:53

+0

不,他們說你的記憶被打破了。它一定是如此! (順便說一句,這是我遇到'未指定的錯誤'後遇到的最愚蠢的錯誤消息)。 – leppie 2012-04-02 19:53:02

回答

0

您正在使用lambda作爲線程函數。這個lambda在新線程上被調用。在實際創建線程的 時刻,它將查找您提供的參數,該參數是一個局部變量srUrl,但到這種情況發生時,您的函數(dispatcherTimer_Tick)已經退出,因此srUrl將處於堆棧不再正確定義(因此訪問衝突)。簡單的解決方法是在類中定義一個變量並快速填充srLoc。更合適的解決方案是實際傳遞srLoc作爲參數:

() => 
{ 
    startNewWindow(srUrl); 
} 

成爲

​​

現在函數引用和字符串的正確副本被保存爲函數調用,並且它不」不管線程開始時,原始的srUrl超出了範圍。我不確定任務工廠是否允許傳遞參數數組。調度員通常對此有重載,所以也許你想讓你的窗口照顧這一點。

現在你實際上做了幾次,所以你可能需要在每次傳遞參數時包裝參數。

+0

感謝您的回答。其實我通過編寫另一個從文件中讀取url的應用程序來解決我的問題。所以我現在開始exes而不是新窗口。有些時候這些新的錯誤提供了錯誤,但軟件繼續運行:)但你的答案是非常專業的,我喜歡它。 – MonsterMMORPG 2012-04-03 13:51:07

+1

@MonsterMMORPG這個答案聽起來很合理,但它是錯誤的。閉包將捕獲局部變量(稱爲自由變量)。另請參閱:http://www.codethinked.com/c-closures-explained – ChrisWue 2012-04-03 19:53:33

+0

如果這是真的,那麼即使顯示窗口,您的代碼也會中斷。顯示窗口後,srUrl未被使用。 – surfen 2012-04-03 20:21:57

1

前段時間我有類似的問題。

發生此錯誤是因爲您的窗口超出了範圍,並且垃圾收集器將其銷燬。

使用ShowDialog()應該解決問題。請注意,這樣做不會阻塞其他線程,因爲該窗口僅在調用線程中模態化。

private void NewWindowThread<T, P>(Func<P, T> constructor, P param) where T : Window 
{ 
    Thread thread = new Thread(() => 
    { 
     System.Windows.Threading.Dispatcher.Run(); 
     T w = constructor(param); 
     w.ShowDialog(); 
     w.Dispatcher.InvokeShutdown(); 
    }); 
    thread.SetApartmentState(ApartmentState.STA); 
    try 
    { 
     thread.Start(); 
    } 
    catch 
    { 
     // log&handle exceptions 
    } 
} 
+0

如果爲true ...您可以通過在加載的事件中設置事件並在退出代理之前等待該事件來做類似事情。 – Yaur 2012-04-02 20:14:21

+0

這是有道理的,但不會阻止新創建的窗口的用戶界面? – surfen 2012-04-02 20:21:42

+0

謝謝你的回答。現在就去嘗試。 – MonsterMMORPG 2012-04-02 21:23:32

2

我一直在與客戶作戰,這是我發現的問題。

我們正在開發一個WPF應用程序,它可以處理很多線程和後臺工作。這個例外突然開始出現,我開始做一些挖掘工作。我終於找到了罪魁禍首大約一個小時的調查後:

 var worker = new BackgroundWorker(); 
     worker.DoWork += (o, ea) => Dispatcher.BeginInvoke(new Action(() => 
     { 
      //do some heavy processing here, plus UI work, then call another method. 

      //inside that other method, I found this: 
      var thread = new Thread(() => 
      { 
       //do some heavy processing. 
      }) { IsBackground = true }; 
      thread.Start(); 
     })); 

什麼似乎已經發生的是,後臺工作即將完成其工作,並從其執行返回。但是,在該後臺工作者內部創建的線程沒有完成處理,並且僅返回以發現它創建的線程已經超出範圍,從而導致AccessViolationException。

爲了調試這個,我建議密切關注發生異常的地方並仔細檢查你的調用堆棧,它可能已經被破壞或丟失,這取決於你是否在線程中拋出異常。

相關問題