Using async method for message loop in C#
async-await, asynchronous, c#, message-loop
Solution
Usually you want to keep track of the task(s) you've started, to avoid re-entrancy and handle exceptions. Example:
Task _messageLoopTask = null;
async void NewMemberCallback(ConnectionController c, Member m, Stream stream)
{
if (_messageLoopTask != null)
{
// handle re-entrancy
MessageBox.Show("Already started!");
return;
}
_messageLoopTask = MessageLoop(c, m,stream,cts.Token);
if (OnNewMember!=null) OnNewMember(m);
try
{
await _messageLoopTask;
}
catch (OperationCanceledException ex)
{
// swallow cancelation
}
catch (AggregateException ex)
{
// swallow cancelation
ex.Handle(ex => ex is OperationCanceledException);
}
finally
{
_messageLoopTask = null;
}
}
Check Lucian Wischik's "Async re-entrancy, and the patterns to deal with it".
If you can have multiple `MessageLoop` instances, then you wouldn't have to worry about re-entrancy, but you'd still want to observe exceptions.
Problem
I'm making an online communication application, and I'd like to process messages asynchronously. I found async-await pattern useful in implementing message loop. Below is what I have got so far: ``` CancellationTokenSource cts=new CancellationTokenSource(); //This is used to disconnect the client. public Action<Member> OnNewMember; //Callback field async void NewMemberCallback(ConnectionController c, Member m, Stream stream){ //This is called when a connection with a new member is established. //The class ConnectionController is used to absorb the difference in protocol between TCP and UDP. MessageLoop(c, m,stream,cts.Token); if(OnNewMember!=null)OnNewMember(m); } async Task MessageLoop(ConnectionController c, Member m, Stream stream, CancellationToken ct){ MemoryStream msgbuffer=new MemoryStream(); MemoryStream buffer2=new MemoryStream(); while(true){ try{ await ReceiveandSplitMessage(stream, msgbuffer,buffer2,ct); //This stops until data is received. DecodeandProcessMessage(msgbuffer); catch( ...Exception ex){ //When the client disconnects c.ClientDisconnected(m); return; } } } ``` Then I got some warning saying that in NewMemberCallback, the call to MessageLoop is not awaited. I actually don't need to await the MessageLoop method because the method does not return until the connection is disconnected. Is it considered a good practice to use async like this? I heard that not awaiting an async method is not good, but I also heard that I should eliminate unnecessary await's. Or is it even considered bad to use async pattern for message loop?