因此,随着我学习越来越多的UWP和XAML,我遇到了两个问题,一个是(我认为)"导航"相关的,第二个是线程问题。我想要实现的目标很简单。我有两页,一页" home"和一个"设置"。在主页上,我将连接的客户端显示为Custom_Buttons。在“设置”页面上,我可以更改有关应用和已连接客户端的一些设置
导航问题
在我的MainPage
上设置我需要的所有声明和对象类。当我导航到一个页面时,我将me
(即MainPage)传递到我正在加载的页面,这样我就可以使用我在MainPage上声明的属性和对象。然后,当我加载页面时,我使用页面事件OnNavigatedTo
来处理传递的MainPage并使用它执行本地stuf。当我经常在页面之间切换应用程序崩溃并打开页面app.g.i.vb并指向以下代码:
#If Debug AndAlso Not DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION Then
AddHandler Me.UnhandledException,
Sub(sender As Global.System.Object, unhandledExceptionArgs As Global.Windows.UI.Xaml.UnhandledExceptionEventArgs)
If Global.System.Diagnostics.Debugger.IsAttached Then
**Here--->>>** Global.System.Diagnostics.Debugger.Break()
End If
End Sub
#End If
导航代码:
Private Sub ListBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
If Home.IsSelected AndAlso Not ScenarioFrame.CurrentSourcePageType Is GetType(Home) Then
BackButton.Visibility = Visibility.Collapsed
ScenarioFrame.Navigate(GetType(Home), Me)
ElseIf Settings.IsSelected AndAlso Not ScenarioFrame.CurrentSourcePageType Is GetType(Settings) Then
BackButton.Visibility = Visibility.Visible
ScenarioFrame.Navigate(GetType(Settings), Me)
End If
End Sub
线程问题
在MainPage上,我声明了一个名为TCP_Server
的类。此类有一个StreamSocketListener
,它使用事件ConnectionReceived
接受新的传入客户端。然后,我只需创建一个表示客户端UI形式的新Object,并将其传递给sub new中Event Args中的StreamSocket
。通过这种方式,每个对象都可以直接从StreamSocket
处理它自己的读写。然后我将这个新对象添加到TCP_Server类中保存的ObservableCollection(Of Object)
。此列表绑定到我在HomePage上使用的Canvas的ItemsSource
,而不是我的MainPage。
Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
MyBase.OnNavigatedTo(e)
If ButtonsList.ItemsSource = Nothing Then ButtonsList.ItemsSource = DirectCast(e.Parameter, MainPage).TCP_Server.Clients
End Sub
当我在ConnectionReceived
中创建此新对象时,我收到错误System.Exception: 'The application has called an interface that has been marshalled for another thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)) '
。它仅在我使用Dispatcher.RunAsync
Private Async Sub TCP_Listener_ConnectionReceived(sender As StreamSocketListener, args As StreamSocketListenerConnectionReceivedEventArgs) Handles TCP_Listener.ConnectionReceived
'Check if the client already excists or not.
Dim client As Client_Button = Clients.FirstOrDefault(Function(x) x.IPaddr = args.Socket.Information.RemoteAddress.ToString)
rootPage.NotifyUser("New Client connected! : [" & args.Socket.Information.RemoteAddress.ToString & "] Total Connected clients = " & Clients.Count, NotifyType.Message)
If client Is Nothing Then
Await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Function()
'Create New object
Dim x As New Client_Button(args.Socket)
'Create new task that runs Async to process incomming data
Dim tsk As Task = Task.Run(Sub() x.ProcessClientAsync())
'Add to the task list so we can stop it later on
ClientTasks.Add(tsk)
'Add it to the Clients List so we can work with the objects
Clients.Add(x)
Return True
End Function)
Else
Await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, Function()
client = Nothing
Clients.Remove(client)
'Create New object
Dim x As New Client_Button(args.Socket)
'Create new task that runs Async to process incomming data
Dim tsk As Task = Task.Run(Sub() x.ProcessClientAsync())
'Add to the task list so we can stop it later on
ClientTasks.Add(tsk)
'Add it to the Clients List so we can work with the objects
Clients.Add(x)
Return True
End Function)
End If
End Sub
答案 0 :(得分:1)
对于您在此处描述的“导航问题”,页面之间多次导航会崩溃,请尝试将页面的NavigationCacheMode
设置为Required
或Enabled
,如下所示:
Public Sub New()
Me.InitializeComponent()
Me.NavigationCacheMode = NavigationCacheMode.Required
End Sub
详情请参阅Page课程的评论。如果您仍有问题,请提供有关“UnhandledException”的详细信息。
对于“线程问题”,使用CoreDispatcher
是正确的方法,这是设计的。 ConnectionReceived
在非UI线程中触发,但您在此事件句柄中调用了UI线程,因此您需要Dispatcher.RunAsync
。更多细节,您可以参考this similar thread。