简体   繁体   English

FromAsync Begin接收冻结的WinForm

[英]FromAsync BeginReceive freezing WinForm

It works great in console application but when I create WinForm, it freezes my form. 它在控制台应用程序中很好用,但是当我创建WinForm时,它冻结了我的表单。

I actually know, why it happens: 我实际上知道为什么会这样:

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);
       }
   }
}

I think, starting the ReceiveAsync-Task method in seperate thread is not an good idea. 我认为,在单独的线程中启动ReceiveAsync-Task方法不是一个好主意。

Can I use the FormAsync without while loop like Async-Methods (BeginXXX, EndXXX)? 是否可以在不使用while循环的情况下使用FormAsync,例如Async-Methods(BeginXXX,EndXXX)?

Thanks in advance! 提前致谢!

Looks like you need to call your second code snippet in separate thread. 看起来您需要在单独的线程中调用第二个代码段。 Otherwise second snippet will simply force asynchronous calls from first snippet to work synchronously (and that is what makes your WindowsForms application to hang - just invoke whole second part of code that You posted in separate thread and it will work ok). 否则,第二个片段将简单地强制从第一个片段执行异步调用(这就是使您的WindowsForms应用程序挂起的原因-只需调用您在单独的线程中发布的整个第二部分代码,它就可以正常工作)。

Edit 编辑

To avoid hanging of application it is possible to slightly change definition of functions that you use - as listed below: 为避免挂起应用程序,可以对所使用的功能的定义稍作更改,如下所示:

    // 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);
               }
           }
        }
    }

then, when you invoke reading socket in a following way, your application will work smoothly (without delays): 然后,当您通过以下方式调用读取套接字时,您的应用程序将顺利运行(无延迟):

// Invokes reading of socket in separate thread
Thread readSocketThread = new Thread(this.PerformRead);
readSocketThread.Start();

Note: You will have to convey data that was read to your windows form controls in some way (for example through some fields or properties or accessing form's fields directly from thread that reads socket). 注意:您将必须以某种方式(例如,通过某些字段或属性,或者直接从读取套接字的线程访问表单的字段),将已读入Windows窗体控件的数据传送给您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM