背景:我正在使用Visual,with VS Community 2013。我正在制作一个Windows窗体应用程序。用例是:用户单击一个按钮。这样就会弹出一个对话框。然后TCP客户端连接到远程服务器,并等待来自服务器的消息。每次消息到达时,对话框上都会显示文本。如果远程侧关闭套接字,则应关闭对话框。此外,用户还可以单击对话框上的一个按钮,该按钮应该关闭套接字并关闭对话框。
除了最后的要求之外,我的代码似乎实现了所有这些。当用户单击按钮关闭对话框时,我会弹出通常的异常,文本如下:
An exception of type 'System.AggregateException' occurred in mscorlib.dll but was not handled in user code.
Additional information: One or more errors occurred.
选择'Break‘显示条件T.Result = 0
被高亮显示。调试器显示T
的值为Id = 1, Status = Faulted {7}, Method = "{null}", Result = "{Not yet computed}"
。
我的问题是:这个错误意味着什么?如何修复它?
下面是对话框代码的相关部分。为了简洁起见,我省略了函数ShowStatus
,它只会更新表单上的可视化控件。
Imports Microsoft.VisualBasic
Imports System.Net.Sockets
Imports System.Text
Public Class FormMyDialog
Private gRequest As String
Private inbuf(10000) As Byte
Private inoff As Integer
Private serv As NetworkStream
Private sock As System.Net.Sockets.TcpClient
' the main form calls this when the user clicks a button
Public Sub Go(request As String)
gRequest = request
ShowDialog()
End Sub
' this is the Close button I have placed on the dialog
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
sock.Close()
End Sub
Private Sub FormMyDialog_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
sock = New System.Net.Sockets.TcpClient()
ShowStatus("Connecting")
sock.Connect("127.0.0.1", 53000)
ShowStatus("Connected")
serv = sock.GetStream()
Dim outbuf As Byte() = Encoding.ASCII.GetBytes(gRequest + Chr(10))
serv.Write(outbuf, 0, outbuf.Length)
serv.Flush()
inoff = 0
ReadLoop()
End Sub
Private Sub ReadLoop()
Dim readlen As Integer
Dim T As Task(Of Integer)
T = serv.ReadAsync(inbuf, inoff, inbuf.Length - inoff)
If T.Result = 0 Then
sock.Close()
Dim d As MethodNoArgs(Of Object)
d = AddressOf Me.Close
Me.Invoke(d)
Return
End If
readlen = T.Result
inoff = inoff + readlen
ProcessInbuf()
T.ContinueWith(Sub() ReadLoop())
End Sub
Public Delegate Sub MethodNoArgs(Of T1)()
Private Sub ProcessInbuf()
' (omitted) processing that calls ShowStatus
' and updates inbuf and inoff
End Sub
End Class
发布于 2015-12-04 10:30:21
您已经注意到,AggregateException
只是多个可能发生的异常的包装器。
我不完全确定为什么这个函数会失败,但是它可能是由您的代码的奇怪结构引起的。我看到的主要问题是,您没有遵循干净的async
-await
结构。通常,您不需要在ContinueWith
和.Result
之间乱搞,在这里得到您想要做的事情。
关键是要使用await
关键字。这个关键字基本上结合了ContinueWith
和.Result
。这意味着它等待非阻塞直到异步操作完成并返回结果。
你的代码实际上可以归结为这样的东西:
Private Async Sub ReadLoop()
Dim readlen As Integer
Do
readlen = Await serv.ReadAsync(inbuf, inoff, inbuf.Length - inoff)
inoff = inoff + readlen
ProcessInbuf()
'maybe this should be async too, to wait until the processing is done
Loop While readlen > 0
sock.Close()
Me.Close()
End Sub
使用Await
的另一个优点是它还可以打开AggregateException
。您只需确保正确处理异常,因为Async Sub
可能因异常而终止,并且不会将异常返回给外部类。一旦它通过了第一个Await
,就会发生这种情况。但是您的代码一旦通过ContinueWith
,就会遇到相同的“问题”。
https://stackoverflow.com/questions/34081152
复制相似问题