FromAsync BeginПолучить заморозку WinForm - PullRequest
0 голосов
/ 03 марта 2012

Отлично работает в консольном приложении, но когда я создаю 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 в отдельном потоке не очень хорошая идея.

Можно ли использовать FormAsync без цикла while, например Async-Methods (BeginXXX, EndXXX)?

Заранее спасибо!

1 Ответ

0 голосов
/ 03 марта 2012

Похоже, вам нужно вызвать второй фрагмент кода в отдельном потоке. В противном случае второй фрагмент просто заставит асинхронные вызовы из первого фрагмента работать синхронно (и это приводит к зависанию вашего приложения 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();

Примечание: Вам придется каким-то образом передавать данные, которые были прочитаны, в элементы управления формы Windows (например, через некоторые поля или свойства или получать доступ к полям формы непосредственно из потока, который читает сокет).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...