顯然,我已經開始以不正確的方式來實現在WPF環境中的3D渲染。 Ofc下面提供了我的問題的解決方案,但我建議閱讀Sheridan答案的更新並使用他的建議來實現此目的。它不僅安全,而且性能也更好。儘管理解它有點複雜,但一旦理解了它,就可以開始在WPF中呈現多個3D應用程序。 感謝您的協助Sheridan!
問題;我在WPF中很新,我想用WPF設計一個連續的渲染(如在遊戲應用程序中)。我正在使用多線程來提供更好的UI控制(開始/停止按鈕fe)。或者由於使用無限循環渲染3D世界,可能會導致事件發生。
但是,我的問題是,當運行該程序時,我得到一個Invalid operation was unhandled
錯誤。問題是有一個對象是主線程的屬性,因此新線程可能無法訪問它。
從XAML文件,
<Grid>
<!-- ui controls omitted ... -->
<Viewport3D Name="myViewport" ClipToBounds="True">
<!-- all inits, camera, pos, ... -->
</Viewport3D>
</Grid>
在主類
;
/// <summary>this method is done to render the 3D app in other thread.</summary>
private void Runtime(Viewport3D vp) {
System.Diagnostics.Debug.WriteLine("runtime ");
Render3D r3d = new Render3D(vp);
// actual startup
while (keepRunning) {
r3d.Init3D();
}
}
/// <summary>this method toggles the game runtime</summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StartOrStop(object sender, RoutedEventArgs e) {
keepRunning = !keepRunning;
if (keepRunning) {
buttonStartStop.Content = "Stop";
// thread
t1 = new Thread(() => Runtime(myViewport));
t1.Start();
}
else {
buttonStartStop.Content = "Start";
t1.Abort();
}
}
3DViewport對象在XAML文件中初始化。這就是爲什麼我將它傳遞給新線程,它可以創建一個使用該3DViewport類的對象。
下面是Render3D
類的示例。
// constructor
internal Render3D(Viewport3D v) {
currViewport = v;
}
/// <summary>get called in loops to render gfx</summary>
internal void Init3D() {
// clear rendered view
ClearRenderWindow();
// add landscape
AddLandScape();
}
/// <summary>clear window to re-render gfx</summary>
private void ClearRenderWindow() {
ModelVisual3D mv;
// ***** error got caught here below ******
for (int i = currViewport.Children.Count - 1; i >= 0; i--) {
mv = (ModelVisual3D)currViewport.Children[i];
if (mv.Content is DirectionalLight == false) currViewport.Children.Remove(mv);
}
}
錯誤發生在currViewport.Children.Count
方法。如前所述,問題在於當前線程沒有該對象的所有權。這是我多線程體驗中第一次面對這個問題。我已經四處搜尋,但找不到解決方案。
有誰知道如何通過Viewport3D對象的所有權,或一個很好的解決方法?
謝謝你的回覆。這是我的課程項目。我知道有更好的選擇(我甚至問我是否被允許使用XNA或DirectX,因爲WPF太有限了)。這是一個「潛水」遊戲,只是在游泳和會見魚類。 :-)嘿,看看這個事件的方法。但是,它甚至需要使用單線程應用程序還是我錯了? – KarelG
再次感謝您。我已經完成了,現在我可以渲染我想要的3D內容。但是,我不知道我應該如何處理'INotifyPropertyChanged'事件。每次Move()調用後我都會觸發它,但是,那又怎樣? – KarelG
很好。在CodeProject上看看[這篇文章](http://www.codeproject.com/Articles/41817/Implementing-INotifyPropertyChanged)...特別是前三個代碼部分。這個想法是每次屬性更新時(來自Move方法),每個屬性都會通知'INotifyPropertyChanged'接口。接口將自動更新UI以反映更改(如果您已正確綁定UI中的屬性)。 – Sheridan