I'm new to C#
s await/async
and currently playing around a bit.
In my scenario I have a simple client-object which has a WebRequest
property. The client should send periodically alive-messages over the WebRequest
s RequestStream
.
This is the constructor of the client-object:
public Client()
{
_webRequest = WebRequest.Create("some url");
_webRequest.Method = "POST";
IsRunning = true;
// --> how to start the 'async' method (see below)
}
and the async alive-sender method
private async void SendAliveMessageAsync()
{
const string keepAliveMessage = "{\"message\": {\"type\": \"keepalive\"}}";
var seconds = 0;
while (IsRunning)
{
if (seconds % 10 == 0)
{
await new StreamWriter(_webRequest.GetRequestStream()).WriteLineAsync(keepAliveMessage);
}
await Task.Delay(1000);
seconds++;
}
}
How should the method be started?
new Thread(SendAliveMessageAsync).Start();
or
Task.Run(SendAliveMessageAsync); // changing the returning type to Task
or
await SendAliveMessageAsync(); // fails as of the constructor is not async
My question is more about my personal understanding of await/async
which I guess may be wrong in some points.
The third option is throwing
The 'await' operator can only be used in a method or lambda marked with the 'async' modifier
How should the method be started?
I vote for "none of the above". :)
"Fire and forget" is a difficult scenario to handle correctly. In particular, error handling is always problematic. In this case, async void
may surprise you.
I prefer to explicitly save the tasks if I'm not await
ing them immediately:
private async Task SendAliveMessageAsync();
public Task KeepaliveTask { get; private set; }
public Client()
{
...
KeepaliveTask = SendAliveMessageAsync();
}
This at least allows the consumers of Client
to detect and recover from exceptions thrown by the SendAliveMessageAsync
method.
On a side note, this pattern is almost equivalent to my "asynchronous initialization" pattern.