简体   繁体   中英

Is this the correct way to wrap a method with a callback for async / await?

I'm working on a library that can send structured messages back and forth across the network. The library has a Send method that takes takes an Action as a callback. When Send is called, the message is sent to the server, when a response is received to that message the stored callback is retrieved and executed.

This all works perfectly, but I would like to add a SendAsync method that wraps Send so that async / await can be used instead of directly passing an Action . I've gotten it to work, but I don't know If I'm doing it correctly, or if I'll run in to problems later. There is one line in particular that is really bothering me.

Send looks like this:

public void Send(Packet packet, Action<Response> callback)
{
    if (packet is Request)
    {
        RegisterResponseCallback(packet, callback);
    }
    Send(packet);
}

The async SendAsync looks like this:

public Task<Response> SendAsync(Request request)
{
    var tcs = new TaskCompletionSource<Response>();
    Send(request, (response) => { tcs.TrySetResult(response); });
    return tcs.Task;
}

I'm calling SendAsync a few time with this code, and I get the correct responses back in the correct order with the correct timing:

private async Task Connected()
{
    Console.WriteLine((await SendAsync(new EchoRequest() { Text = "Test 1" })).Message);
    Console.WriteLine((await SendAsync(new EchoRequest() { Text = "Test 2" })).Message);
    Console.WriteLine((await SendAsync(new EchoRequest() { Text = "Test 3" })).Message);

The line that is bothering me is the one that calls Connected . It's inside a method that I don't want to mark async for various reasons.

protected override void StatusChanged(NetIncomingMessage message)
{
    switch (message.SenderConnection.Status)
    {
        case NetConnectionStatus.Connected:
            _serverConnection = new ServerConnection(this, message.SenderConnection);
            (new Task(async () => { await Connected(); })).Start();
            break;
    }
}

Specifically, the line that reads (new Task(async () => { await Connected(); })).Start(); feels really "smelly" to me, but this was the only way I could figure out to get Visual Studio to stop giving me warnings.

Have I wrapped Send correctly for async /await, or will anything I've done here cause me problems further down the line? Is there a better way for me to call Connected ?

I think StatusChanged is an event handler? Thus you need async void .

protected override async void StatusChanged(NetIncomingMessage message)
{
    //use await here
}

EDIT Since it's not an event handler, and you have various reasons not to mark it async , the only suggestion I can give is: using Task.Run instead of new Task , it's probably the most suitable solution here if you don't want to change the signature of the method.

Task.Run(async() => await Connected());

new Task vs Task.Factory.StartNew

Task.Run vs Task.Factory.StartNew

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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