通过异步服务器通讯/等待? [英] Server communication via async/await?

查看:162
本文介绍了通过异步服务器通讯/等待?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要创建的Socket消息通过异步通过TAP发送/等待。

I want to create Socket message sending via TAP via async/await.

答案并的这个 - 我决定创建一个完全工作示例:

After reading this answer and this one - I decided to create a fully working sample :

那么,什么有我尝试:

我从<一的TAP extenstion方法href=\"http://stackoverflow.com/questions/21539766/receive-correct-amount-of-data-tcp/21540278#21540278\">here (一切OK了),我就在控制台CMD测试:

I took the TAP extenstion methods from here (all ok) : and I test it in console cmd :

Reciever code

public static class SocketExtensions
{
    public static Task<int> ReceiveTaskAsync(this Socket socket, byte[] buffer, int offset, int count)
    {
        return Task.Factory.FromAsync<int>(
                         socket.BeginReceive(buffer, offset, count, SocketFlags.None, null, socket),
                         socket.EndReceive);
    }

    public static async Task<byte[]> ReceiveExactTaskAsync(this Socket socket, int len)
    {
        byte[] buf = new byte[len];
        int totalRead = 0;
        do{
            int read = await ReceiveTaskAsync(socket, buf, totalRead, buf.Length - totalRead);
            if (read <= 0) throw new SocketException();
            totalRead += read;
        }while (totalRead != buf.Length);
        return buf;
    }

    public static Task ConnectTaskAsync(this Socket socket, string host, int port)
    {
        return Task.Factory.FromAsync(
                         socket.BeginConnect(host, port, null, null),
                         socket.EndConnect);
    }

    public static Task SendTaskAsync(this Socket socket, byte[] buffer)
    {
        return Task.Factory.FromAsync<int>(
                         socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, null, socket),
                         socket.EndSend);
    }
}
static   void  Main()
{
      Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      s.ConnectTaskAsync("127.0.0.1", 443);


      var buf1 =    s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
      Console.Write(Encoding.UTF8.GetString(buf1.Result)); 

      var buf2 =   s.ReceiveExactTaskAsync(100); //read exactly 100 bytes
      Console.Write(Encoding.UTF8.GetString(buf2.Result));

      Console.ReadLine();
}

发件人code:

// use same extension method class like above ....^

   void  Main()
    {
     Socket s = new Socket(SocketType.Stream    , ProtocolType.Tcp);
     s.ConnectTaskAsync( "127.0.0.1" , 443);
     s.SendTaskAsync(Encoding.UTF8.GetBytes("hello"));

     s.Close();
     Console.ReadLine();
    }

注意我删除了异步从主要因为即时通讯在控制台测试。

notice I removed the async from main since im testing it in console.

问题,

根据上述环线,code应该工作

According to link above , the code should work

不过我越来越也不例外,它只是挂在该行:

However I'm getting no exception and it's just hangs on that line :

Console.Write(Encoding.UTF8.GetString(buf1.Result));

(首先我运行接收器,然后我跑发送)

我是什么失踪?

推荐答案

这个问题来自于请注意我删除了异步从主要因为即时通讯在控制台测试。的。

您需要等待的操作做下一步之前完成。在code你为榜样暂停使用每个等待的操作来完成,您的code只是去直接通过。

You need to wait for the operation to complete before doing the next step. The code you used as an example pauses at each await for the operation to complete, your code just goes straight through.

您可以通过将解决这个问题一个 .Wait(),将有一个每个操作的await 或通过 Task.Run运行的线程池线程内这个函数(然而的我觉得这是更好地知道什么时候你应该使用异步当你不应该。

You may be able to fix this by putting a .Wait() after each operation that would have had a await or by running this function inside a threadpool thread via Task.Run(, however I think it is better to know when you should use async and when you should not.

异步时,应使用有其他的工作,你可以有螺纹做,非常普遍,其他工作将东西像一个WinForms项目处理UI消息或接受新的连接一个ASP.NET网站。在一个控制台应用程序有程序可以做,而等待没有其他的工作,所以在这种情况下,它会更适合使用的功能同步版本而不是。

Async should be used when you have other work you could have the thread be doing, very commonly that "other work" will be things like processing UI messages on a WinForms project or accepting new connections on a ASP.NET site. In a console application there is no other work your program could be doing while it waits, so in that situation it would be more appropriate to use the synchronous version of the functions instead.

P.S。您提出的意见后,我贴的这就是为什么我删除了异步等待并用Task.result 的,只是让你知道永远的曾经 1 结合code,使用等待和code,阻止同步大赛(通过使用像 Task.Result Task.Wait(),你可能会导致您的code死锁和停止工作!

P.S. You made the comment after I posted "that's why I remove the async awaits and used Task.result", just so you know never ever1 combine code that uses await and code that blocks the synchronization contest (by using things like Task.Result or Task.Wait(), you will likely cause your code to deadlock and stop functioning!

这是不是你的当前例如问题,因为控制台应用程序没有同步的情况下,但如果你复制粘贴此code的东西,没有你可以很容易地锁定您的程序。

It is not a issue for your current example because console applications do not have a synchronization context, but if you copied and pasted this code to something that did you could easily lock up your program.

1:好吧,你可以结合等待和阻断code,但也有需要遵循的规则,但如果你知道足够的争议我你知道我的意思,足以安全地做到这一点。如果你不知道如何安全地做它只是避免做

1: Ok, you could combine await and blocking code but there are rules you need to follow, but if you know enough to dispute my what I am saying you know enough to safely do it. If you don't know how to safely do it just avoid doing it

这篇关于通过异步服务器通讯/等待?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆