它在控制台应用程序中工作得很好,但是当我创建WinForm时,它冻结了我的表单。
我其实知道,为什么会这样:
public static Task<int> ReceiveAsync(this Socket socket, byte[] buffer, int offset, int size, SocketFlags flags = SocketFlags.None)
{
if (socket == null) throw new Exception("Socket is null.");
var tcs = new TaskCompletionSource<int>(socket);
socket.BeginReceive(buffer, offset, size, flags, iar =>
{
var t = (TaskCompletionSource<int>)iar.AsyncState;
var s = (Socket)t.Task.AsyncState;
try { t.SetResult(s.EndReceive(iar)); }
catch (Exception exc) { t.SetException(exc); }
}, tcs);
return tcs.Task;
}
while ((byteRead = ReceiveAsync(socket, buffer, 0, buffer.Length, SocketFlags.None).Result) > 0)
{
lock (buffer)
{
try
{
byte[] dBuffer = decompressor.Decompress(buffer);
lock (dBuffer)
{
string receivedData = Encoding.UTF8.GetString(dBuffer);
OnRead(receivedData, byteRead);
}
}
catch (Exception ex)
{
Client.Base.Log.Save(ex);
socket.Shutdown(SocketShutdown.Both);
}
}
}我认为,在分离线程中启动ReceiveAsync-Task方法不是一个好主意。
我可以使用没有while循环的异步方法(BeginXXX,EndXXX)的FormAsync吗?
提前感谢!
发布于 2012-03-03 22:45:53
看起来你需要在单独的线程中调用你的第二个代码片段。否则,第二个代码片段只会强制第一个代码片段的异步调用同步工作(这就是WindowsForms应用程序挂起的原因--只需调用您在单独线程中发布的整个第二部分代码,它就可以正常工作)。
编辑
为了避免应用程序挂起,可以稍微更改您使用的函数的定义,如下所示:
// Is not changed
public static Task<int> ReceiveAsync(this Socket socket, byte[] buffer, int offset, int size, SocketFlags flags = SocketFlags.None)
{
if (socket == null) throw new Exception("Socket is null.");
var tcs = new TaskCompletionSource<int>(socket);
socket.BeginReceive(buffer, offset, size, flags, iar =>
{
var t = (TaskCompletionSource<int>)iar.AsyncState;
var s = (Socket)t.Task.AsyncState;
try { t.SetResult(s.EndReceive(iar)); }
catch (Exception exc) { t.SetException(exc); }
}, tcs);
return tcs.Task;
}
// Moved to new function
public void PerformRead()
{
while ((byteRead = ReceiveAsync(socket, buffer, 0, buffer.Length, SocketFlags.None).Result) > 0)
{
lock (buffer)
{
try
{
byte[] dBuffer = decompressor.Decompress(buffer);
lock (dBuffer)
{
string receivedData = Encoding.UTF8.GetString(dBuffer);
OnRead(receivedData, byteRead);
}
}
catch (Exception ex)
{
Client.Base.Log.Save(ex);
socket.Shutdown(SocketShutdown.Both);
}
}
}
}然后,当您通过以下方式调用读取套接字时,您的应用程序将顺利工作(没有延迟):
// Invokes reading of socket in separate thread
Thread readSocketThread = new Thread(this.PerformRead);
readSocketThread.Start();注意:您必须以某种方式(例如,通过某些字段或属性,或者直接从读取socket的线程访问表单字段)将读取到windows窗体控件的数据传送给windows窗体控件。
https://stackoverflow.com/questions/9546396
复制相似问题