如何从异步方法返回一个类

时间:2017-07-05 06:38:38

标签: c# asynchronous async-await

是否可以从异步方法返回一个类?我收到一条错误消息,指出GetAwaiter丢失了?不知道这意味着什么。

StatusButton.Click += async (sender, e) =>
        {
            ...             
            byte[] TheResponse = new byte[1024];
            await TheResponse = client.Read(); // <---- GetAwaiter ?
        };          

public class Client
{
    ...

    public async Task<byte[]> Read()
    {
        var ns = tcpClient.GetStream();
        byte[] Result = new byte[1024];
        await ns.ReadAsync(Result, 0, Result.Length);
        return Result;
    }
}

3 个答案:

答案 0 :(得分:2)

  

是否可以从异步方法返回一个类?

  

我收到一条错误消息,指出GetAwaiter丢失了,这是什么意思?

这意味着变量TheResponse被声明为byte[],但您尝试将其指定为Task<byte[]>。但是,IDE会对async关键字的使用进行抢先检查,并向您抱怨您尝试等待的类型没有GetAwaiter方法。这是因为它是byte[]。以下是展示此问题的示例.NET fiddle

我想在这里引起很多关注。首先,当您的返回类型为TaskTask<T>或任何其他异步返回类型时 - 最佳做法是使用“Async”后缀命名该方法,即; ReadAsync。此外,明确比这更明显。由于您只能从此方法返回Task<byte[]>,我们称之为ReadBytesAsync,是吗?

好的,现在我们有一个明确定义的客户端和相应的API让我们看一下它的用法。当您使用允许使用相应async关键字的await关键字时。这两个关键字协同工作,永远不能单独使用。

Task<byte[]>视为一种承诺,在某个时候我会给你一个byte[],但你必须“等待”这个。在您的代码中,您将await置于错误的位置。相反,你应该有以下内容:

StatusButton.Click += async (sender, e) =>
    {
        ...

        byte[] bytes = await client.ReadBytesAsync();
    };

没有理由声明和初始化变量只是为了尝试重新分配它,就像你所做的那样。相反,简单地声明并将等待的调用响应中的值初始化为.ReadBytesAsync调用。请注意,如果没有await关键字,您将拥有代表异步操作的Task<byte[]>

答案 1 :(得分:0)

非常感谢,现在它运行了。不得不做出一些改变。他们在这里:也许有人可以使用它。

    protected override void OnCreate(Bundle bundle)
    {
        ...

        OpenButton.Click += delegate
        {
            SendCommand('O');
            ThreadPool.QueueUserWorkItem(o => ShutDown());
        };

        ...
    }


    async void SendCommand(Char Command)
    {
        ... //Command not used in this part of code

        const string sn = "SEND_NONCE";

        byte[] data = System.Text.Encoding.ASCII.GetBytes(sn);

        Client client = new Client();

        TcpClientPacket TheData = new TcpClientPacket(sn.Length);

        TheData.Buffer = data;
        TheData.Length = sn.Length;

        bool IsConnected = await client.InitializeAsync(HostUrl, Port);

        ...

        await client.WriteAsync(TheData);

        TcpClientPacket TheResponse = await client.ReadAsync(16);

        ...

    }


    public class Client
    {
        private TcpClient tcpClient;

        public async Task <bool> InitializeAsync(string ip, int port)
        {
            tcpClient = new TcpClient();
            try
            {
                await tcpClient.ConnectAsync(ip, port);
            }
            catch
            {
                return false;
            }
            return tcpClient.Connected;
        }

        public void Deactivate()
        {
            tcpClient.Close();
        }

        public async Task WriteAsync(TcpClientPacket Data)
        {
            var ns = tcpClient.GetStream();
            await ns.WriteAsync(Data.Buffer, 0, Data.Length);
        }

        public async Task<TcpClientPacket> ReadAsync(int ExpectedLength)
        {
            var ns = tcpClient.GetStream();
            TcpClientPacket Result = new TcpClientPacket(ExpectedLength);
            Result.Length = await ns.ReadAsync(Result.Buffer, 0, ExpectedLength);
            return Result;
        }

    }

    public class TcpClientPacket
    {
        public byte[] Buffer;
        public int Length;

        public TcpClientPacket(int Size)
        {
            Buffer = new byte[Size];
            Length = 0;
        }
    }

答案 2 :(得分:-1)

StatusButton.Click += async (sender, e) =>
{
    ...
    byte[] TheResponse = new byte[1024];
    TheResponse = await client.Read();          // <---- place await in the correct place
};