C# await udpClient.ReceiveAsync() fails and terminates program - c#

I'm running a C# console application with .NET 4.5.1. When I run the following function the udpClient.ReceiveAsync() call below silently terminates the program with no exception. How do I debug this?
public async void Run()
{
try
{
var armIpAddress = IPAddress.Parse("239.1.11.1");
using (var udpClient = new UdpClient())
{
udpClient.ExclusiveAddressUse = false;
var ipEndPoint = new IPEndPoint(IPAddress.Any, 12020);
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.ExclusiveAddressUse = false;
udpClient.Client.Bind(ipEndPoint);
udpClient.JoinMulticastGroup(armIpAddress);
while (true)
{
var result = await udpClient.ReceiveAsync();
//...
}
}
catch (Exception x)
{
Console.WriteLine(x.Message);
}
}

The call to await udpClient.ReceiveAsync() is not terminating the program nor it is silently failing.
Given that this is happening, I assume you have something like this:
public static void Main(string[] args)
{
...
Run();
}
In an async void method, control is returned to the parent as soon as an await call is reached, so the flow of the program would be something like:
public static void Main(string[] args)
{
...
var armIpAddress = IPAddress.Parse("239.1.11.1");
using (var udpClient = new UdpClient())
{
udpClient.ExclusiveAddressUse = false;
.......
while (true)
{
return;
}
}
}
So the program ends due to no further blocking code.
For this to work as you would expect, change the code to this:
public static void Main(string[] args)
{
...
Run().Wait();
}
public async Task Run() { ... }

Not sure about the calling method, but with the given infomation, I would suggest the following article that has best practices around async await by #Stephen Cleary
It says to avoid async void and I am pasting an excerpt here from the article for quick reference
Async void methods can wreak havoc if the caller isn’t expecting them to be async. When the return type is Task, the caller knows it’s
dealing with a future operation; when the return type is void, the
caller might assume the method is complete by the time it returns.
This problem can crop up in many unexpected ways.
Exceptions from an Async Void Method Can’t Be Caught with Catch

Related

a thread doesn't work when I use ToListAsync method

I have an EF Core program.
Code
class EagerLoading
{
public async void load()
{
Console.WriteLine("a");
var teams = await loadTeamsAsync();
Console.WriteLine("c");
}
public async Task<List<Team>> loadTeamsAsync()
{
Console.WriteLine("b");
using (var context = new SchoolContext())
{
return await context.teams.
ToListAsync();
}
}
}
//Entry method
static void Main(string[] args)
{
new EagerLoading().load();
}
Output
a
b
Expected
a
b
c
Question
where am I wrong? why the Console.WriteLine("c"); doesn't execute?
You will need to put a ReadKey or similar in the Main method to stop the application from exiting.
Load is an async void (which should be ringing alarm bells) and runs unobserved, in-turn there is a high probability of the application exiting before it finishes in the way you expect (or in this case writing to the console).
static void Main(string[] args)
{
new EagerLoading().load();
Console.ReadKey();
}
Note : You should only ever be using on async voids on event handlers (or constructs that logically represent event handlers), it's more-or-less the primary reason they exist.

Suggested pattern for gracefully restart cancelled async Tasks on non UI application

I have a console app that instantiates a WeatherClientManager class.
The main thread in the console app requests current weather status in the WeatherClientManager class, but the WeatherClientManager class continuously receives data from a server.
In code:
public static void Main(string [])
{
Program p = new Program();
Task.Run(()=>p.RunLoop());
}
class Program{
WeatherClientManager wcM;
public void RunLoop()
{
wcM = new WeatherClientManager ();
await wcM.InitiateConnection().ConfigureAwait(false);
}
}
class WeatherClientManager
{
public async Task<bool> InitiateConnection()
{
TCPClient tcpClient = new TcpClient(GetTCPDetailsFromConfig())
await tcpClient.ConnectAsync()
CancellationTokenSource cts = new CancellationTokenSource();
if(tcpClient.Connected)
{
Task.Run(()=>ReceiveTask(cts.Token));
Task.Run(()=>SendKeepAlive(cts.Token));
return true;
}
return false;
}
private void ReceiveTask(CancellationToken t)
{
try{
networkStream.Receive(..) // throws exception
}
catch(Exception e)
{
Stop(e);
}
}
private void SendKeepAlive(CancellationToken t)
{
while(!t.IsCancellationRequested)
{
try{
networkStream.Write(..) // throws exception
}
catch(Exception e)
{
Stop(e);
}
}
}
private void Stop(Exception e )
{
log.Error(e);
e.Cancel();
}
}
One of many crap ideas I have is:
Task.Run( () =>
{
while(true)
{
var t1 = Task.Run(()=>ReceiveTask(cts.Token));
var t2= Task.Run(()=>SendKeepAlive(cts.Token));
try{
Tasks.WhenAny(); // should block
}
catch(Exception e)
{
}
finally{
Cleanup();
InitiateConnections();
}
}
}
But I hate the idea of spinning a task to control two sub tasks. My problem is where and how to re-initiate the connection. Any ideas?
EDIT:
I've updated the code such that WeatherClientManager has a OnDisconnectDetected event. So the Program.cs class subscribes like so:
weatherServerManager.OnDisconnectDetected += HandleDisconnectDetection
public async void HandleDisconnectDetection()
{
wsM = new WeatherClientManager ();
wsM.InitiateConnection().ConfigureAwait(false);
}
private void SendKeepAlive(CancellationToken t)
{
while (...)
{
try{}
catch(Exception e)
{
OnDisconnectDetected?.Invoke();
}
}
}
When the handler is invoked by the WeatherClientManager it creates a new task that should continue in a different context. The KeepAlive task should exit then.
Still feels hacky but ideas welcome!
As a general rule, I prefer composition of methods over raising events. In particular, avoid the Task.Run-based fire-and-forget.
In the case of asynchronous sockets, I think it makes sense to give each socket a main loop:
class WeatherClientManager
{
public async Task MainLoop()
{
TCPClient tcpClient = new TcpClient(GetTCPDetailsFromConfig())
await tcpClient.ConnectAsync();
CancellationTokenSource cts = new CancellationTokenSource();
var receiveTask = Task.Run(()=>ReceiveTask(cts.Token));
var keepaliveTask = Task.Run(()=>SendKeepAlive(cts.Token));
await Task.WhenAll(receiveTask, keepaliveTask);
}
}
These can then be composed into the main program's main loop:
class Program
{
public async Task RunLoop()
{
while (true)
{
wcM = new WeatherClientManager();
await wcM.MainLoop();
}
}
}
which in turn is composed into Main:
public static void Main(string [])
{
Program p = new Program();
p.RunLoop().GetAwaiter().GetResult();
}
By avoiding fire-and-forget, you're ensuring that your code will always observe all exceptions. Ignoring tasks is occasionally okay but usually a mistake.

C# async method call

I would have a async call to a function as following:
I'll call a method from the main method, this function should be async, how I do this?
A little example:
private static void Main(string[] args)
{
StartDoingNothingAsync();
Console.WriteLine("test");
Console.Read();
}
private static async void StartDoingNothingAsync()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
}
I would first the output "test", before "leaved", how can I practice this?
The simplest option would be to introduce a delay into your async method:
private static async void StartDoingNothingAsync()
{
await Task.Delay(1000);
// This will be called on a thread-pool thread
Console.WriteLine("leaved");
}
That won't guarantee that test will be printed before leaved, but it seems very likely. If you actually want a guarantee, you'd have to pass something into StartDoingNothingAsync that you then signal after printing test... but it's not really clear what you're trying to achieve.
Note that async methods should almost never be void - basically that's only available to allow for async event handlers. Make the method return Task instead - that way your calling code can tell when it's completed. (Even if you don't use that fact in this case, it's a good habit to get into.)
Now that we have a bit more information about what you're trying to achieve, I would recommend not making StartDoingNothingAsync an async method - just use a task instead:
private static void Main(string[] args)
{
Task task = Task.Run(DoSomething);
Console.WriteLine("test");
task.Wait();
Console.Read();
}
static void DoSomething()
{
// Code to run on a separate thread
}
You can do it like this
private static void Main(string[] args)
{
StartDoingNothingAsync();
Console.WriteLine("test");
Console.Read();
}
private static async void StartDoingNothingAsync()
{
await Task.Run(async delegate()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
});
}
You can use Task for that. In that case you don't need to mark your function as async:
private static void Main(string[] args)
{
new Task(StartDoingNothing).Start();
Console.WriteLine("test");
Console.Read();
}
private static void StartDoingNothing()
{
for (var i = 0; i < 5000; i++)
{
//do something
}
Console.WriteLine("leaved");
}

Async exception handling with void

I'm using Async CTP to write an IO heavy console app. But I'm having problems with exceptions.
public static void Main()
{
while (true) {
try{
myobj.DoSomething(null);
}
catch(Exception){}
Console.Write("done");
//...
}
}
//...
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
And the following happens: "done" gets written to the console, then I get the exception in the debugger, then I press continue my program exists.
What gives?
If you give your Console application an async-compatible context (e.g., AsyncContext (docs, source) from my AsyncEx library), then you can catch exceptions that propogate out of that context, even from async void methods:
public static void Main()
{
try
{
AsyncContext.Run(() => myobj.DoSomething(null));
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
Console.Write("done");
}
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
When you call DoSomething() it basically creates a Task under the hood and starts that Task. Since you had a void signature, there is no Task object to signal back or that you could have blocked on, so execution fell straight through to done. Meanwhile the task throws an exception, which nobody is catching, which, I suspect, is why your program terminates.
I think the behavior you wanted is more like this:
public static void Main()
{
while (true) {
var t = myobj.DoSomething(null);
t.Wait();
if(t.HasException) {
break;
}
}
Console.Write("done");
//...
}
}
//...
public async Task DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
This will block on each DoSomething until it's done and exit the loop if DoSomething threw. Of course, then you are not really doing anything async. But from the pseudo code, i can't quite tell what you wanted to happen asynchronously.
Main take-away: Using void for an async method means that you loose the ability to get the exception unless you are awaiting that async method. As a sync call it basically just schedules work and the outcome disappears into the ether.

Why does asynchronous delegate method require calling EndInvoke?

Why does the delegate need to call the EndInvoke before the method fires? If i need to call the EndInvoke (which blocks the thread) then its not really an asynchronous call is it?
Here is the code im trying to run.
class Program
{
private delegate void GenerateXmlDelegate();
static void Main(string[] args)
{
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(null, null);
}
private static void GenerateMainXml()
{
Thread.Sleep(10000);
Console.WriteLine("GenerateMainXml Called by delegate");
}
}
The reason you need to call EndInvoke is to avoid memory leaks; .Net will store information about the function's result (or exception) until you call EndInvoke.
You can call EndInvoke in the completion handler that you give to BeginInvoke and retain the asyncronous nature.
EDIT:
For example:
class Program {
private delegate void GenerateXmlDelegate();
static void Main(string[] args) {
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(delegate {
try {
worker.EndInvoke();
} catch(...) { ... }
}, null);
}
private static void GenerateMainXml() {
Thread.Sleep(10000);
Console.WriteLine("GenerateMainXml Called by delegate");
}
}
If you want to fire an async call and forget about it, you can use the ThreadPool, like this:
ThreadPool.QueueUserWorkItem(delegate { GenerateMainXml(); });
As SLaks said, EndInvoke insures against memory leaks.
BeginInvoke is still asynchronous; consider the following code:
static void Main() {
Func<double> slowCalculator = new Func<double>(PerformSlowCalculation);
IAsyncResult slowCalculation = slowCalculator.BeginInvoke(null, null);
// lots of stuff to do while slowCalculator is doing its thing
Console.WriteLine("Result is {0}", slowCalculator.EndInvoke(slowCalculation));
}
static double PerformSlowCalculation() {
double result;
// lots and lots of code
return result;
}
If this code were written without the BeginInvoke/EndInvoke calls, PerformSlowCalculation would have to finish before Main could do the rest of its "lots of stuff"; this way, the two can be happening at the same time.
Now, in your example using a GenerateXmlDelegate, you still need EndInvoke even though you're not returning anything. The way to do this is:
static void Main(string[] args) {
GenerateXmlDelegate worker = new GenerateXmlDelegate(GenerateMainXml);
IAsyncResult result = worker.BeginInvoke(GenerateXmlComplete, null);
}
private static void GenerateXmlComplete(IAsyncResult result) {
AsyncResult realResult = result as AsyncResult;
GenerateXmlDelegate worker = result.AsyncDelegate as GenerateXmlDelegate;
worker.EndInvoke();
}

Categories

Resources