这是用异步/等待回调包装方法的正确方法吗?

问题描述:

我工作的,可以发送结构化消息来回在网络库。该库有一个Send方法,需要将Action作为回调。当调用Send时,消息被发送到服务器,当收到该消息的响应时,存储的回调将被检索并执行。这是用异步/等待回调包装方法的正确方法吗?

这一切都完美的工作,但我想添加一个SendAsync方法,包装Send,以便可以使用异步/等待,而不是直接传递Action。我已经得到它的工作,但我不知道如果我正确地做,或者如果我以后会遇到问题。特别有一条线真的困扰着我。

Send看起来是这样的:

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

异步SendAsync看起来是这样的:

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

我打电话SendAsync这个代码的一些时间,我也得到了正确的反应早在与正确的时间正确的订单:

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

困扰我的线路是那个叫Connected的线路。这是一种方法,我不想标记async由于各种原因。

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

具体来说,读取(new Task(async() => { await Connected(); })).Start();行,感觉很“臭”给我,但是这是我能想出获得Visual Studio中停止给我警告的唯一途径。

有我包Send正确的异步/ AWAIT,或将任何东西我还这里做使我的问题了线?有没有更好的方式给我打电话Connected

我觉得StatusChanged是事件处理程序?因此你需要async void

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

编辑因为它不是一个事件处理程序,你有各种理由不将其标记为async,我能给的唯一建议是:使用Task.Run代替new Task,它可能是这里如果最合适的解决方案你不想改变方法的签名。

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

new Task vs Task.Factory.StartNew

Task.Run vs Task.Factory.StartNew

+0

不,这不是一个事件处理程序。由于从定时器轮询的服务器接收到消息,它会从库中的更深处调用。因此,'async void'感觉不对,我读过的所有内容都表示,对于任何不是偶处理程序的东西,通常都是*错误,因此被声明为异步无效。 –

+0

@BradleyUffner是的,我们应该避免使用'async void',除了事件处理程序。它的名字看起来像是我的事件处理程序。如果这是一种正常的方法,那么为什么你不能使它成为'async'呢?你说'这是一种我不想因各种原因标记异步的方法。为什么? –

+0

我不得不改变它返回一个'任务',对吗?然后,无论什么样的电话都要等待,等等,直到我将异步和任务完成到“Main”。我承认,我对异步/等待很陌生,所以我可能会误解一些东西。 'StatusChanged'并不是异步发生的,用异步标记它并让它返回任务就好像我将代码中的异步模式混合在一起,而我从来不打算异步执行异步模式。 –