Windows商店应用程序至少可以说令人沮丧; 只是足够接近常规.net进入麻烦.
我在使用Tasks,await和Socket.ConnectAsync时遇到的问题.
我有以下代码:
public async TaskConnect(string hostName, int portNumber) { string result = string.Empty; // Create DnsEndPoint. The hostName and port are passed in to this method. DnsEndPoint hostEntry = new DnsEndPoint(hostName, portNumber); // Create a stream-based, TCP socket using the InterNetwork Address Family. _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // Create a SocketAsyncEventArgs object to be used in the connection request SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); socketEventArg.RemoteEndPoint = hostEntry; // Inline event handler for the Completed event. // Note: This event handler was implemented inline in order to make this method self-contained. socketEventArg.Completed += new EventHandler (delegate (object s, SocketAsyncEventArgs e) { // Retrieve the result of this request result = e.SocketError.ToString(); // Signal that the request is complete, unblocking the UI thread _clientDone.Set(); }); // Sets the state of the event to nonsignaled, causing threads to block _clientDone.Reset(); // Make an asynchronous Connect request over the socket await _socket.ConnectAsync(socketEventArg); // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds. // If no response comes back within this time then proceed _clientDone.WaitOne(TIMEOUT_MILLISECONDS); return result; }
我开始在Async/await中添加到应用程序以防止UI问题.但是当我进入这个功能并添加了Await时
await _socket.ConnectAsync(socketEventArg);
我收到错误:
错误CS1929'bool'不包含'GetAwaiter'的定义,并且最佳扩展方法重载'WindowsRuntimeSystemExtensions.GetAwaiter(IAsyncAction)'需要类型为'IAsyncAction'的接收器
在查看ConnectAsync的文档时,看起来ConnectAsync应该支持等待...
它不支持等待吗?
不,ConnectAsync
不是TAP方法,因此不能用await
.
对于使用原始套接字的任何人来说,我的#1建议是"不要".如果可以,请使用REST API(带HttpClient
)或SignalR
API.原始插座有很多陷阱.
如果你必须使用原始套接字(即,另一方使用自定义TCP/IP协议,而你没有权力修复这种情况),那么首先要注意的是Socket
该类有三个完整的API全部在一节课.
第一个是看似简单的同步API(Connect
),我不建议任何生产代码.第二个是标准APM模式(BeginConnect
/ EndConnect
).第三种是特定于Socket
class(ConnectAsync
)的专用异步模式; 这个专用API比标准异步API要复杂得多,只有在受限环境中进行繁琐的套接字通信时才需要,并且需要通过垃圾收集器减少对象流失.
请注意,没有await
兼容的API.我没有和微软的任何人谈过此事,但我强烈怀疑他们只是认为Socket
班级已经有太多成员(3个完整的API;增加一个await
兼容的API 会添加第四个完整的API),这就是为什么它当他们将TAP模式(await
兼容)成员添加到BCL中的其他类型时被跳过.
正确使用的API - 很容易99.999%的时间 - 是APM的API.您可以使用创建自己的TAP包装器(使用它await
)TaskFactory.FromAsync
.我喜欢用扩展方法来做这个,像这样:
public static Task ConnectTaskAsync(this Socket socket, EndPoint remoteEP) { return Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, remoteEP, null); }
然后你可以在任何地方调用它Socket
,如下:
await _socket.ConnectTaskAsync(hostEntry);