2016-03-15 73 views
0

我工作的,可以發送結構化消息來回在網絡庫。該庫有一個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

回答

3

我覺得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'並不是異步發生的,用異步標記它並讓它返回任務就好像我將代碼中的異步模式混合在一起,而我從來不打算異步執行異步模式。 –