C# Async Console Input Behaviour [duplicate] - c#

This question already has answers here:
Adding a short delay inside a loop prevents it from looping indefinitely. Why?
(2 answers)
Why does Console.In.ReadLineAsync block?
(3 answers)
Closed 1 year ago.
I want to make a C# Console App, that can evaluate user input while it is doing some work. For that I want to await the Input asynchron similar to this: await Console.ReadLine(). For testing purpose I simply want the main work loop to stop running when I hit Enter. I have achieved that like this:
using System;
using System.Threading;
using System.Threading.Tasks;
class WorkTillEnter
{
private static bool running = false;
public static void Main(string[] args)
{
WorkTillEnter.running = true;
WorkTillEnter.observeInputAsync();
DateTime lastTick = DateTime.Now;
while(WorkTillEnter.running){
if(lastTick.Second != DateTime.Now.Second){
Console.WriteLine($"Tick {DateTime.Now}");
lastTick = DateTime.Now;
}
//Doing Work in this loop until enter is hit
}
Console.WriteLine("Worker Terminated.");
}
private static async void observeInputAsync(){
await Task.Delay(1); // <--WHY???
await Console.In.ReadLineAsync();
WorkTillEnter.running = false;
}
}
This works fine and prints Ticks every Second until Enter is hit. My Qustion is now: Why does it not work when I delete this one Line? await Task.Delay(1); // <--WHY??? Whithout this Line the programm does nothing until I hit return, and then obviously never enters the while loop. How can this behavior be explained?
This suggestion Why does Console.In.ReadLineAsync block? explaines why Console.In.ReadLineAsyncisn't behaving as expected when my questionable Line is removed. But it does not explain why it actualy beahaves as expected when the Line is added.

Here await Task.Delay(1); making sure that your program enters into the while loop. If you don't use this, the function waits for an input. When the input is given, the boolean value of running becomes false and the program never gets into the loop.
I don't know why on earth await Console.In.ReadLineAsync(); is blocking for an input. Maybe it's a bug. 🤷🏻‍♂️
A simple debugging process like this can help to understand the situation.
using System;
using System.Threading.Tasks;
class WorkTillEnter
{
private static bool running;
public static void Main(string[] args)
{
Console.WriteLine("a");
running = true;
Console.WriteLine("b");
ObserveInputAsync();
Console.WriteLine("c");
DateTime lastTick = DateTime.Now;
Console.WriteLine("d");
while (running)
{
Console.WriteLine("e");
if (lastTick.Second != DateTime.Now.Second)
{
Console.WriteLine($"Tick {DateTime.Now}");
lastTick = DateTime.Now;
}
//Doing Work in this loop until enter is hit
}
Console.WriteLine("f");
Console.WriteLine("Worker Terminated.");
}
private static async void ObserveInputAsync()
{
Console.WriteLine("1");
await Task.Delay(1); // <--WHY???
Console.WriteLine("2");
await Console.In.ReadLineAsync();
running = false;
Console.WriteLine("3");
}
}

Thx to Andreas Huber for giving the reason. Console.In.ReadLineAsync() is bugged and actualy blocking until Input is submited. But the questionable Line pushes the async function to a new Thread. Testing the code like this:
using System;
using System.Threading;
using System.Threading.Tasks;
class WorkTillEnter
{
private static bool running = false;
public static void Main(string[] args)
{
WorkTillEnter.running = true;
Console.WriteLine($"before Asnyc called: {Thread.CurrentThread.ManagedThreadId}");
WorkTillEnter.observeInputAsync();
Console.WriteLine($"after Asnyc called: {Thread.CurrentThread.ManagedThreadId}");
DateTime lastTick= DateTime.Now;
while(WorkTillEnter.running){
if(lastTick.Second != DateTime.Now.Second){
Console.WriteLine($"Tick {DateTime.Now}");
lastTick = DateTime.Now;
}
//Doing Work in this loop until enter is hit
}
Console.WriteLine("Worker Terminated.");
}
private static async void observeInputAsync(){
Console.WriteLine($"Async before await: {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(1); // <--WHY???
Console.WriteLine($"Async after first await: {Thread.CurrentThread.ManagedThreadId}");
await Console.In.ReadLineAsync();
Console.WriteLine($"Async after second await: {Thread.CurrentThread.ManagedThreadId}");
WorkTillEnter.running = false;
}
}
results in output: (you can see at which point i hit return)
before Asnyc called: 1
Async before await: 1
after Asnyc called: 1
Async after first await: 4
Tick 11.05.2021 20:30:42
Tick 11.05.2021 20:30:43
Async after second await: 4
Worker Terminated.
but with the line removed gives output like this:
before Asnyc called: 1
Async before await: 1
Async after first await: 1
Async after second await: 1
after Asnyc called: 1
Worker Terminated.

Related

c# - How to execute code on the main thread until a Task finishes

I'd like to understand the TPL a little bit better. How would I for example write something to the screen until a task finishes. I can't call 'await' because I want the main thread to be notified instead of proactively calling 'await' and I don't want to stop execution until the task is finished.
Some example code:
var task = Task.Run(()=>
{
Task.Delay(10000);
});
while(true)
{
Console.WriteLine("Running...");
//I want to exit the loop the second 'task' finishes
//and print 'finished'
}
There are a a couple of ways you cam achieve this:
First you can use Lambda expression in Order to invoke your action, but look at the code:
using System;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Console.WriteLine("Application thread ID: {0}",
Thread.CurrentThread.ManagedThreadId);
var t = Task.Run(() => { Console.WriteLine("Task thread ID: {0}",
Thread.CurrentThread.ManagedThreadId);
} );
t.Wait();
}
}
// The example displays the following output:
// Application thread ID: 1
//
notice the t.Wait():
The call to the Wait method ensures that the task completes and
displays its output before the application ends. Otherwise, it is
possible that the Main method will complete before the task finishes.
So we understand that it's imperative to call the Wait() method in order make sure that the task completes and displays its output.
You can use the second way also:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var list = new ConcurrentBag<string>();
string[] dirNames = { ".", ".." };
List<Task> tasks = new List<Task>();
foreach (var dirName in dirNames) {
Task t = Task.Run( () => { foreach(var path in Directory.GetFiles(dirName))
list.Add(path); } );
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
foreach (Task t in tasks)
Console.WriteLine("Task {0} Status: {1}", t.Id, t.Status);
Console.WriteLine("Number of files read: {0}", list.Count);
}
}
For more reference see Task.Run Method.
One highlight regarding your quesion:
taken from Asynchronous programming with async and await (C#):
An async method typically contains one or more occurrences of an await
operator, but the absence of await expressions doesn’t cause a
compiler error. If an async method doesn’t use an await operator to
mark a suspension point, the method executes as a synchronous method
does, despite the async modifier. The compiler issues a warning for
such methods.
That implies that either way you will have to wait for your tasks to finish and the main thread will have to wait this way or another.
The ContinueWith function is a method available on the task that allows executing code after the task has finished execution. In simple words it allows continuation.
Things to note here is that ContinueWith also returns one Task. That means you can attach ContinueWith one task returned by this method.
Task<string> t = Task.Run(() => LongRunningOperation("Continuewith", 500));
t.ContinueWith((t1) =>
{
Console.WriteLine("Running...");
});
You can achieve your goal using creating separate function to use in Task.Run and passing parameter by reference. Function should be something like below.
private void PerformTask(ref bool isComplete)
{
System.Threading.Thread.Sleep(5000);
isComplete = true;
}
Call above function from Task.Run. Your current function should be like below.
bool isComplete = false;
System.Threading.Tasks.Task.Run(() => PerformTask(ref isComplete));
while (!isComplete)
{
Console.WriteLine("Running...");
System.Threading.Thread.Sleep(1000);
}
Try to do something like this:
var task = Task.Run(() =>
{
Task.Delay(10000).Wait();
});
bool terminate = false;
while (!task.GetAwaiter().IsCompleted && !terminate)
{
// do something
if (task.GetAwaiter().IsCompleted) break;
// do something heavy
if (task.GetAwaiter().IsCompleted) break;
// do another heavy operation
for (int i = 0; i < 10000; i++)
{
// it took too long!
if (i == 1000)
{
terminate = true;
break;
}
}
}

Use of Async and await in console Application

I have four methods.
Main: only calls the preform method
Working: displays "please wait for the user"
Taking Time: A program that takes time to execute.
Preform: Calls the taking time and working methods asynchronously.
The following is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncObservation
{
class Program
{
static void Main(string[] args)
{
preform();
}
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
Thread.Sleep(1000);
Console.WriteLine("The Program finished");
}
public static async void preform()
{
Task timer = Takingtime();
Task wait = Working();
}
}
}
In the end: I need to display
This program started.
Please wait, the program is running
The program ended.
I see several problems in your program.
Although Preform is neither async nor an event handler, it does not return a Task
The tasks started in Preform are not awaited for before you finish Preform. Hence you never know when they are finished, nor what the results are (exception?). You could even end your program before they are finished
After you start a Task it is not guaranteed when it will run. You can only be sure that statements are already executed if you await for the Task.
Using async-await is a method to make sure that your thread looks around to see if it can do useful stuff instead of waiting idly if it has to wait for something. Thread.Sleep is a busy wait. If you want to look around to see if you can do something else use await Task.Delay(TimeSpan.FromSeconds(1)) instead.
In your case, you can't be sure that any Console line has been written until you await the procedure that should write your line. If you start your second Task before awaiting the first, you don't know how far the first task already proceeded, and thus you don't know for sure that the text already has been written to the Console.
C# 7.1 introduced async Task Main(), so you could use that instead of the traditional void Main. It saves you from catching and interpreting the AggregateException that is thrown by the Task you start to make your process async.
If you don't want to use the async Main, you can of course use Task.Run to call an async function:
static void Main(string[] args)
{
try
{
var preformTask = Task.Run( () => Preform() );
DoSomethingElse(); // if needed
preformTask.Wait(); // wait for preformTask to finish
Console.WriteLine("Task completed; press any key to finish");
Console.ReadKey();
}
catch (Exception exc) // inclusive ggregateException if one of your Task fails
{
ProcessException(exc)
}
}
static async Task preform()
{
// To be certain that the Console Line has been written: await
await Takingtime();
// if here, you are certain that the Line has been written,
// or course you have lost parallel processing
await Working();
}
For completeness: the other functions
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
// either return a completed Task, or await for it (there is a difference!
await Task.CompletedTask;
// or:
return Task.CompletedTask; // do not declare async in this case
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
//Use Task.Delay instead of Sleep
await Task.Delay(TimeSpan.FromSeconds(1); // improved readability
Console.WriteLine("The Program finished");
}
Because of the awaits in Preform you are certain that the text has been written. However, you've lost some parallellism.
If you really want those procedures to execute at the same time, you can't be certain about when text will be written. If that is important, then split the Parts that should be run first (write Console) from the parts that should run in parallel (Task.Delay)
static async Task preform()
{
// Do the things that should be done before parallel tasks are run
await DoThisFirst();
// start the Tasks that can work parallel: not sure what statements are executed first
var taskA = DoTaskA();
var taskB = DoTaskB();
// if here, you are free to do something else
// can't be sure about the status of taskA nor taskB
DoSomethingElse();
// if you want to do something after you know that the tasks have completed:
// await the tasks here:
await Task.When (new Task[] {taskA, taskB});
// if here, you are certain that all parallel tasks have completed successfully
// if desired fetch the return values of the Tasks:
var returnValueA = taskA.Result;
var returnValueB = taskB.Result;
// do all async things of which you needed to be certain that both tasks finished
// for example:
await ProcessResults(returnValueA, returnValueB);
}
In a console app it is OK to use a .Wait() call in an void Main method.
In some contexts where there is synchronisation necessary .Wait() can cause deadlocks (ASP.NET has a request to synchronise on or XAML/WinForms which have a UI thread), but there is nothing to synchronise on here.
static void Main()
{
preform.Wait()
}
This will wait for the async work to complete synchronously. You need the method to run synchronously so that it does not return early. If you use async void and await the method will return immediately and exit the method, await does not work in a Main method.
I would also suggest using await Task.Delay(1000); rather than Thread.Sleep(1000); as this is the canonical async way to idle.
For your code example:
class Program
{
static void Main(string[] args)
{
preform().Wait();
Console.ReadLine();
}
public static async Task Working()
{
Console.WriteLine("Please wait, the program is running");
}
public static async Task Takingtime()
{
Console.WriteLine("This Program started");
await Task.Delay(1000);
Console.WriteLine("The Program finished");
}
public static Task preform()
{
return Task.WhenAll(
Takingtime(),
Working());
}
}
Use Stephen Cleary's Nito.AsyncEx library (available via Nuget) to provide an asynchronous context for a console application. See here for more details.
Your application can then be written as ...
class Program
{
static int Main(string[] args)
{
try
{
Console.WriteLine("The application has started");
AsyncContext.Run(() => LongRunningTaskAsync(args));
Console.WriteLine("The application has finished");
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return -1;
}
}
static async Task LongRunningTaskAsync(string[] args)
{
Console.WriteLine("The long running task has started");
// use Task.Delay() rather than Thread.Sleep() to avoid blocking the application
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
Console.WriteLine("The long running task has finished");
}
}
Use preform().Wait() in the constructor. So the call is awaited. Then use await Takingtime() and await Working() in the preform method.
And you have to change the return type to Task.

C# - Run code in background and continue with current method

I am new to async/await in C#. This is what I'm trying to do:
private async Task LoadSomeData()
{
/*
*This is where the 'Data' is loaded with HTTP
*/
//Data loading finished. Need to return control to next line from caller function and use this 'Data'
// Also need to use 'Data' to load 'Data2' over HTTP but is not very important
// and hence can be run in background. No piece of code depends on this currently.
}
private async void UIEventHandler()
{
//await until 'Data2' has loaded
//Continue handling the event after Data2 is loaded
}
My question is, how do I achieve the above operation. I don't want to return from LoadSomeData() method after retrieving Data2 as the current operation does not depend on it.
Below is some quick code I threw together around your method names. I've made them static just for convenience.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Console.WriteLine("Main Start");
UIEventHandler(2000);
UIEventHandler(500);
UIEventHandler(1000);
Console.WriteLine("Main Stop");
Thread.Sleep(3000); // wait for tasks to finish
}
private static async Task LoadSomeData(int delay)
{
await Task.Run(() =>
{
Console.WriteLine("Start (LoadSomeData) " + delay);
Thread.Sleep(delay);
Console.WriteLine("Stop (LoadSomeData) " + delay);
});
}
private static async Task UIEventHandler(int delay)
{
Console.WriteLine("Start (UIEventHandler) " + delay);
await LoadSomeData(delay);
Console.WriteLine("Stop (UIEventHandler) " + delay);
}
}
This is sample output from a test run:
Main Start
Start (UIEventHandler) 2000
Start (LoadSomeData) 2000
Start (UIEventHandler) 500
Start (UIEventHandler) 1000
Main Stop
Start (LoadSomeData) 500
Start (LoadSomeData) 1000
Stop (LoadSomeData) 500
Stop (UIEventHandler) 500
Stop (LoadSomeData) 1000
Stop (UIEventHandler) 1000
Stop (LoadSomeData) 2000
Stop (UIEventHandler) 2000
You will notice that every call to UIEventHandler showed it's "Start" message straight away. However, the "Stop" message is not shown until the respective call to LoadSomeData is complete. The await operator is essentially telling the code in UIEventHandler to stop until the task in the called method is complete.
That's a really simplistic view of it, though. I'd suggest doing some reading. This might be a good start:
Asynchronous programming
private async Task LoadSomeData()
{
var data = await Task.Delay(1000); // Replace with your HTTP GET
return data;
}
private async Task LoadSomeData2(Data data)
{
var data2 = await Task.Delay(1000); // Replace with your other HTTP GET
return data2;
}
private async void UIEventHandler()
{
var data = await LoadSomeData();
var data2 = await LoadSomeData2(data);
}
UPDATE:
I recommend you read Async/Await - Best Practices in Asynchronous Programming

Program exits upon calling await

I have a while-loop that should repeat the program until a certain condition is met. Inside this loop I call an async function, which prints out a message for me. Here is the (cut-short) code:
private void InitializeMessageSystem ( )
{
do
{
// Do stuff
await printMessage ("Hello World!");
Console.ReadKey();
} while (condition != true)
}
And here the function PrintMessage():
private static async Task PrintMessage (string message, int spd = 1)
{
int delay = 50 / spd;
string[] words = message.Split(' ');
int index = 1;
for (int word = 0; word < words.Length; word++)
{
char[] current = words[word].ToCharArray();
if (index + current.Length > Console.WindowWidth)
{
Console.WriteLine();
index = 1;
}
for (int c = 0; c < current.Length; c++)
{
Console.Write(current[c]);
await Task.Delay(delay);
}
Console.Write(" ");
}
}
Edit: Here's the call from the main function:
static void Main (string[] args)
{
InitializeMessageSystem();
Console.ReadKey();
}
Question
Why does my program exit, when I press a key while the function is not yet completed? I thought the program would wait for the Console.ReadKey() until the function PrintMessage() is completed?
Your problem is that await returns the control flow of the program to the caller of the function. Normally execution is continued at that point when the asynchronous task you await finishes.
So control is returned to your main function as you wait for printMessage and main now waits for a key input. As you hit the key main returns to the OS and your process (including all asynchronous tasks) terminates.
Change your InitializeMessageSystem to
private async Task InitializeMessageSystem ( )
and change the code in main to
InitializeMessageSystem().Wait();
to wait until InitializeMessageSystem finishes completely before waiting for the key.
The below code executes without any errors or warnings. But when you execute the code the program exits silently. What you might be expecting is the program waits for the task to complete, asks the user to press any key and exit. What actually happens is after the await statement is executed the control goes back to the invoking step. In our case after the step await task; is executed, before the task completes the control goes back to the invoking step SomeTask(); and the program exits.
class Program
{
static void Main(string[] args)
{
SomeTask();
}
public static async void SomeTask()
{
Task task = Task.Run(() =>
{
System.Threading.Thread.Sleep(20000);
Console.WriteLine("Task Completed!");
});
await task;
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
To fix this, add await to the SomeTask(); call so that the program waits for async SomeTask() to complete. You should also change the return type
of SomeTask() from void to Task.
class Program
{
static void Main(string[] args)
{
await SomeTask();
}
public static async Task SomeTask()
{
Task task = Task.Run(() =>
{
System.Threading.Thread.Sleep(20000);
Console.WriteLine("Task Completed!");
});
await task;
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
The difference between calling a synchronous function and an async function is that when calling the synchronous function you know that when you reach the statement after the call the function is executed completely. When calling an async function, the function is scheduled as a task at the thread pool to be performed when any of the threads in the pool has time for it.
This gives you time to do other things while one of the threads is performing the task. As soon as you need the result you await for the task to be finished.
This works only if your function is also async. If you don't make your function async your can't use async-await. Making your function async and the clients of your function also async is the only way to truly use async-await. Remember: all async functions should return Task instead of void and Task<TResult> instead of TResult. The only exception is the event handler
private async void Button1_Clicked(object sender, ...)
{
var myTask = SlowMultiplierAsync(4, 3);
// while myTask is running you can do other things
// after a while you need the result:
int taskResult = await myTask;
Process(taskResult);
}
private async Task<int> SlowMultiplierAsync(int x, int y)
{
// let's take a nap before multiplying
// do this by awaiting another async function:
await Task.Delay(TimeSpan.FromSeconds(5));
return x * y;
}
If you don't want (or can) make your function async, you can simulate similar behaviour by starting a task using task.Run:
private void InitializeMessageSystem ( ) {
do
{
// Do stuff
var myTask = task.Run( () => printMessage ("Hello World!"));
myTask.Wait();
Console.ReadKey();
} while (condition != true)
Although this will make sure that your function won't end before the task is finished, your function will be a synchronous one for your clients. For instance it won't make your UI responsive.
Eric lippert here on stackoverflow once explained me the difference between asynchronous concurrent. Link to his answer
Suppose you have to make breakfast. Toast some bread and cook some eggs.
Synchronous: start toasting bread. Wait until toasting finished. Start cooking eggs, wait until eggs are cooked.
Asynchronous but not concurrent: start toasting bread, and while the bread is toasting start cooking eggs. While the eggs are cooking yo can do other things, like making tea. After a while you wait until the eggs are cooked and wait until the bread is toasted. This is typically async-await.
Asynchronous and concurrent: hire a cook to toast the bread, hire a cook to cook the eggs and wait until both cooks are finished. Here the toasting and cooking is done by different threads. It is the most expensive method

Using 'async' in a console application in C# [duplicate]

This question already has answers here:
Can't specify the 'async' modifier on the 'Main' method of a console app
(20 answers)
Closed 5 years ago.
I have this simple code:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Great. This compiles.
But let’s say I have a console application and I want to run the code above (calling SumTwoOperationsAsync()).
static void Main(string[] args)
{
SumTwoOperationsAsync();
}
But I've read that (when using sync) I have to sync all the way up and down:
Does this mean that my Main function should be marked as async?
Well, it can't be because there is a compilation error:
an entry point cannot be marked with the 'async' modifier
If I understand the async stuff , the thread will enter the Main function → SumTwoOperationsAsync → will call both functions and will be out. But until the SumTwoOperationsAsync
What am I missing?
In most project types, your async "up" and "down" will end at an async void event handler or returning a Task to your framework.
However, Console apps do not support this.
You can either just do a Wait on the returned task:
static void Main()
{
MainAsync().Wait();
// or, if you want to avoid exceptions being wrapped into AggregateException:
// MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
...
}
or you can use your own context like the one I wrote:
static void Main()
{
AsyncContext.Run(() => MainAsync());
}
static async Task MainAsync()
{
...
}
More information for async Console apps is on my blog.
Here is the simplest way to do this
static void Main(string[] args)
{
Task t = MainAsync(args);
t.Wait();
}
static async Task MainAsync(string[] args)
{
await ...
}
As a quick and very scoped solution:
Task.Result
Both Task.Result and Task.Wait won't allow to improving scalability when used with I/O, as they will cause the calling thread to stay blocked waiting for the I/O to end.
When you call .Result on an incomplete Task, the thread executing the method has to sit and wait for the task to complete, which blocks the thread from doing any other useful work in the meantime. This negates the benefit of the asynchronous nature of the task.
notasync
My solution. The JSONServer is a class I wrote for running an HttpListener server in a console window.
class Program
{
public static JSONServer srv = null;
static void Main(string[] args)
{
Console.WriteLine("NLPS Core Server");
srv = new JSONServer(100);
srv.Start();
InputLoopProcessor();
while(srv.IsRunning)
{
Thread.Sleep(250);
}
}
private static async Task InputLoopProcessor()
{
string line = "";
Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);
while(line != "quit")
{
Console.Write(": ");
line = Console.ReadLine().ToLower();
Console.WriteLine(line);
if(line == "?" || line == "help")
{
Console.WriteLine("Core NLPS Server Help");
Console.WriteLine(" ? or help: Show this help.");
Console.WriteLine(" quit: Stop the server.");
}
}
srv.Stop();
Console.WriteLine("Core Processor done at " + DateTime.Now);
}
}

Categories