首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FromAsync BeginReceive冻结WinForm

FromAsync BeginReceive冻结WinForm
EN

Stack Overflow用户
提问于 2012-03-03 21:13:26
回答 1查看 540关注 0票数 0

它在控制台应用程序中工作得很好,但是当我创建WinForm时,它冻结了我的表单。

我其实知道,为什么会这样:

代码语言:javascript
复制
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吗?

提前感谢!

EN

回答 1

Stack Overflow用户

发布于 2012-03-03 22:45:53

看起来你需要在单独的线程中调用你的第二个代码片段。否则,第二个代码片段只会强制第一个代码片段的异步调用同步工作(这就是WindowsForms应用程序挂起的原因--只需调用您在单独线程中发布的整个第二部分代码,它就可以正常工作)。

编辑

为了避免应用程序挂起,可以稍微更改您使用的函数的定义,如下所示:

代码语言:javascript
复制
    // 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);
               }
           }
        }
    }

然后,当您通过以下方式调用读取套接字时,您的应用程序将顺利工作(没有延迟):

代码语言:javascript
复制
// Invokes reading of socket in separate thread
Thread readSocketThread = new Thread(this.PerformRead);
readSocketThread.Start();

注意:您必须以某种方式(例如,通过某些字段或属性,或者直接从读取socket的线程访问表单字段)将读取到windows窗体控件的数据传送给windows窗体控件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9546396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档