如何从UWP应用程序(vb.net)中的后台任务在主UI线程上引发事件

如何从UWP应用程序(vb.net)中的后台任务在主UI线程上引发事件,vb.net,uwp,task,Vb.net,Uwp,Task,我试图从UWP类库后台任务引发一个事件,但我需要在我计划使用类库的UWP应用程序的主UI线程上封送它。不过,我正在寻找一种从后台任务中将其封送的方法。我浏览了几篇文章,包括这篇: 但这对我来说毫无意义。有人能帮我写下面的代码吗 Private ReceiveTask As New Task(Sub() Dim InStream As Stream = CSocket.InputStream.AsStreamF

我试图从UWP类库后台任务引发一个事件,但我需要在我计划使用类库的UWP应用程序的主UI线程上封送它。不过,我正在寻找一种从后台任务中将其封送的方法。我浏览了几篇文章,包括这篇: 但这对我来说毫无意义。有人能帮我写下面的代码吗

    Private ReceiveTask As New Task(Sub()    
                                    Dim InStream As Stream = CSocket.InputStream.AsStreamForRead    
                                    While killswitch = False    
                                        Try    
                                            Dim Reader As StreamReader = New StreamReader(InStream)    
                                            Dim DataText As String = ""    
                                            While Reader.Peek <> -1    
                                                DataText &= Convert.ToChar(Reader.Read)    
                                            End While    
                                            RaiseEvent DataReceived(DataText)    
                                        Catch ex As Exception    
                                            RaiseEvent SocketError("Receiving", ex.Message)    
                                        End Try    
                                    End While    
                                End Sub)    
Private ReceiveTask作为新任务(Sub()
作为流的Dim流入=CSocket.InputStream.AsStreamForRead
而killswitch=False
尝试
作为StreamReader的Dim读卡器=新StreamReader(流内)
Dim DataText As String=“”
而Reader.Peek-1
DataText&=Convert.ToChar(Reader.Read)
结束时
已接收RaiseEvent数据(DataText)
特例
RaiseEvent插座错误(“接收”,例如消息)
结束尝试
结束时
末端接头)
感谢jmcilhinney,下面的代码可以工作

    Private ReceiveTask As New Task(Sub()
                                    Dim InStream As Stream = CSocket.InputStream.AsStreamForRead
                                    While killswitch = False
                                        Try
                                            Dim Reader As StreamReader = New StreamReader(InStream)
                                            If Reader.Peek <> -1 Then
                                                DataText = ""
                                                While Reader.Peek <> -1
                                                    DataText &= Convert.ToChar(Reader.Read)
                                                End While
                                                uiContext.Post(AddressOf RaiseDataToUI, Nothing)
                                            End If
                                        Catch ex As Exception
                                            ReceiveError = ex.Message
                                            uiContext.Post(AddressOf RaiseErrorToUI, Nothing)
                                        End Try
                                    End While
                                End Sub)
Private ReceiveTask作为新任务(Sub()
作为流的Dim流入=CSocket.InputStream.AsStreamForRead
而killswitch=False
尝试
作为StreamReader的Dim读卡器=新StreamReader(流内)
如果Reader.Peek-1那么
DataText=“”
而Reader.Peek-1
DataText&=Convert.ToChar(Reader.Read)
结束时
uiContext.Post(地址为RaiseDataToUI,无任何内容)
如果结束
特例
ReceiveError=ex.Message
uiContext.Post(RaiseErrorToUI的地址,无)
结束尝试
结束时
末端接头)

我自己没有做过任何UWP开发,但我相信正确的方法是使用
同步上下文,就像在WPF中一样。其原理是,
SynchronizationContext.Current
属性将生成类的特定于线程的实例,因此您可以在UI线程上获取该属性的值,然后在其他地方使用该对象封送对所属线程的调用。属性值通常在UI线程上创建的对象的构造函数中检索,例如

Imports System.Threading

Public Class SomeClass

    'Get the context for the thread on which the current instance is created.
    Private uiContext As SynchronizationContext = SynchronizationContext.Current

    Private Sub ThisMethodIsCalledOnASecondaryThread()
        uiContext.Post(AddressOf ThisMethodIsCalledOnTheUIThread, Nothing)
    End Sub

    Private Sub ThisMethodIsCalledOnTheUIThread(data As Object)
        'Execute UI thread logic here, e.g. raise an event.
    End Sub

End Class

从某种意义上说,我现在可以将事件提升到UI。但是我已经用测试服务器软件测试了我的测试客户机,看起来uiContext.post无法足够快地将信息发送到UI。我从插座里漏掉了一大堆信息。任务。延迟似乎毫无帮助。有什么想法吗?没关系,它很管用。在事件触发之前正在清除缓冲区。将为其他人发布正确的代码。在上面的示例中,我已将
Nothing
传递给
post
方法的第二个参数。我看到您在最终代码中也做了同样的操作,这表明您必须在
raiseerrotoui
方法中读取数据。您最好在调用
Post
并将其传递给该参数之前读取该数据。然后,您将收到它作为您调用的方法顶部的参数。这意味着,在此期间,数据的原始源发生了什么都无关紧要。好主意,我已经实现了,谢谢提示!)