Is there no way to Wait in C#? - c#

There is a command that usually makes the program wait. Now I know how to make the Program wait while also freezing all input, but that's not what I'm trying to achieve. I'm making a simple Windows Console Application, just to start me up on things.
String name;
Console.WriteLine("What is your name?");
name = Console.ReadLine();
Console.WriteLine("Hello, {0}", name);
Now I'd like to have it wait while also allowing any input, so that way I could run something else, but also have it to where you can actually have it say Hello, (Insert Name Here)
And also, as mentioned before that I'm very new, please try to explain what you're answer involves, thanks!

Outside of ReadLine which you are already using that waits for user input, Thread.Sleep as in below is one basic method of stopping the application for X amount of time to wait for an execution to finish or a user to be ready. Thread.Sleep blocks execution though in more complex applications:
Thread.Sleep(2000);
Getting into an advanced way, you can use Asynchronous programming concepts and use Task.Delay. This doesn't block a thread like sleep and it means you can do this using a single thread using the async programming model. This sample code creates a new method, says it's async and defines it as a Task which is basically a unit of work, again more advanced concept wise but just to give you a high level idea/overview.
async Task TaskDelay()
{
await Task.Delay(2000);
}
private async void Test()
{
// Console.WriteLine etc. etc
await PutTaskDelay();
MessageBox.Show("Hello, I'm done waiting.");
}

I believe the question is:
How do wait in the main thread for user input, while working on some other task in the background?
class Program
{
static void Main(string[] args)
{
AsynchronousTask();
Console.WriteLine("What is your name?");
var name = Console.ReadLine();
Console.WriteLine("Hello, {0}", name);
Console.ReadLine();
}
private static async void AsynchronousTask()
{
Task.Run(() =>
{
while (true)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Async tas is running in the background.");
Console.ForegroundColor = ConsoleColor.White;
Thread.Sleep(1000); //this is just to slowdown background thread
}
});
}
}
While this example is very basic it shows how to get some code running in background. The topic you may wish to explore is called Asynchronous Programing

Related

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.

What causes a Task to complete?

I'm trying to find out how to use WhenAll to let two methods run at once, and once they both finish, collect the results without blocking by using .Result
I have this little console app test:
using System.Diagnostics;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
public static void Main(string[] args)
{
var run = TaskRunner();
Debug.WriteLine(run);
if (run.IsCompleted)
{
Debug.WriteLine("this worked!");
} else
{
Debug.WriteLine("this failed!");
}
}
public static async Task<string> TaskRunner()
{
var taskOne = OneAsync();
var taskTwo = TwoAsync();
var tasks = await Task.WhenAll(taskOne, taskTwo);
var retval = tasks[0] + tasks[1];
return retval;
}
public static Task<string> OneAsync()
{
return Task.Run(() =>
{
return "test1";
});
}
public static Task<string> TwoAsync()
{
return Task.Run(() =>
{
return "test2";
});
}
}
}
This currently prints this worked! to my Output window... However, if I comment out Debug.WriteLine(run); it prints this failed!... Why does the Task complete simply by being logged to the output window?
I'm trying to understand a huge problem in a complex piece of code and this little test is my MCVE to hopefully shed some light on what is happening behind the scenes.
This happens just by pure chance. The way you are starting your task is with Task.Run. This essentially creates a new thread on which the (synchronous) action is executed. It returns a task for the completion of that thread.
So OneAsync and TwoAsync will each spawn a new thread that then immediately returns a string. This will happen very quickly but there’s still some overhead for creating those threads which means that it won’t be instantaneous.
TaskRunner then calls both those methods (spawning the threads), and then asynchronously waits for both threads to finish. Since the threads are not completely instantly, this TaskRunner method also won’t complete instantly.
Now, in your main, you are starting the asynchronous TaskRunner, which we figured will take “a very short moment”. You do not await the task, so the execution continues immediately. Debug.WriteLine is executed to print something (it probably doesn’t really matter that it’s the task in question that is being printed), and then you are checking the state of the task.
Since printing stuff is relatively slow (compared to other operations), this is probably the reason why the tasks ends up being completed. And when you remove the printing, the if is just reached too quickly for the task to finish.
As you likely noticed, working like that with asynchronous tasks does not appear to be a good idea. That’s why you should always await the task when you depend on its result.
// note the *async* here; async main methods are supported with C# 7.1
public static async void Main(string[] args)
{
var run = TaskRunner();
// await the task
await run;
if (run.IsCompleted)
{
Debug.WriteLine("this worked!");
}
else
{
Debug.WriteLine("this failed!");
}
}

Task.Wait() not waiting for task to finish

I have a console app and I want to launch tasks one after the other.
Here is my code:
static void Main()
{
string keywords = "Driving Schools,wedding services";
List<string> kwl = keywords.Split(',').ToList();
foreach(var kw in kwl)
{
Output("SEARCHING FOR: " + kw);
Task t = new Task(() => Search(kw));
t.Start();
t.Wait();
}
Console.ReadLine();
}
static async void Search(string keyword)
{
// code for searching
}
The problem is that it doesn't wait for the first task to finish executing. It fires off the subsequent tasks concurrently.
I am working with a rate limited API so I want to do one after the other.
Why is it not waiting for one search to finish before starting the next search?
Your async method just returns void, which means there's no simple way of anything waiting for it to complete. (You should almost always avoid using async void methods. They're really only available for the sake of subscribing to events.) Your task just calls Search, and you're waiting for that "I've called the method" to complete... which it will pretty much immediately.
It's not clear why you're using async at all if you actually want to do things serially, but I'd suggest changing your code to look more like this:
static void Main()
{
// No risk of deadlock, as a console app doesn't have a synchronization context
RunSearches().Wait();
Console.ReadLine();
}
static async Task RunSearches()
{
string keywords = "Driving Schools,wedding services";
List<string> kwl = keywords.Split(',').ToList();
foreach(var kw in kwl)
{
Output("SEARCHING FOR: " + kw);
await Search(kw);
}
}
static async Task Search(string keyword)
{
// code for searching
}

c# Console Application - Run for(;;) loop while not disturbing rest of executing code

I have a C# console application that needs to call a function immediately when the application begins running, in this example ExecuteForLoop(); .
This is how my C# console application starts running:
static void Main()
{
ExecuteForLoop();
Console.Write("Test");
}
the function ExecuteForLoop() in this example does this:
ExecuteForLoop()
{
int example = 0;
for(;;)
{
example++;
}
}
The problem is that if I call the ExecuteForLoop() function the Console.Write("Test"); function will not execute immediately. "Test" will ONLY be outputted to my console once the for(;;) loop within ExecuteForLoop() stops looping.
How can I call ExecuteForLoop() and continue executing code so the function Console.Write("Test"); will be outputted to my C# console application while the for(;;) loop within the ExecuteForLoop() function is still running?
You should almost never use Thread directly.
Use Tasks instead. They are a higher-level abstraction and are much easier to work with than threads.
A simple example:
var backgroundTask = Task.Run(() =>
{
Console.WriteLine("Background task started");
while (true)
{
//do something
}
});
Console.WriteLine("Back in main");
Console.ReadKey();
Another one, cancelling the task after a key is pressed and returning a result:
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var backgroundTask = Task.Run(() =>
{
Console.WriteLine("Background task started");
long count = 0;
while (!token.IsCancellationRequested)
{
count++;
}
Console.WriteLine("Background task cancelled");
return count;
}, token);
Console.WriteLine("Back in main");
Console.ReadKey();
tokenSource.Cancel();
Console.WriteLine("Counter: {0}", backgroundTask.Result);
Console.ReadKey();
A great resource to learn more about tasks is Stephen Cleary's blog.
Create a Thread and run your logic inside
static void Main()
{
Thread t = new Thread (ExecuteForLoop); // Kick off a new thread
t.Start();
Console.Write("Test");
t.Join(); // wait for thread to exit.
}
I recommend reading Albahari articles/blog on threading, it is very detailed.
Use multi-threading:
static void Main()
{
var t = new Thread(() => ExecuteForLoop());
t.Start();
Console.Write("Test");
t.Join() // See this answer : http://stackoverflow.com/a/14131739/4546874
}
Also, that might not exactly be what you want. Are you sure you need an infinite for-loop in the method? If not, see the syntax for a for-loop and set an exit condition accordingly.
"Test" is not printed because in the previous line you call the ExecuteForLoop() method, in which the program runs into an infinite loop. Since, both statements are in the same thread, the latter cannot be executed unless the previous is, which of course is impossible.

Why does await Task take considerably longer than return Task

I have made an interesting observation which I would like to fully understand.
The easiest way to explain this is by capturing it with this little sample console application:
namespace AsyncAwaitTestApp
{
using System;
using System.Diagnostics;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
var timer = new Stopwatch();
// First Run:
// -------------------------
Console.WriteLine("Running GiveMeATask in parallel...");
timer.Start();
Parallel.For(0, 500, (i) =>
{
SillyClass.GiveMeATask().Wait();
});
timer.Stop();
Console.WriteLine($"GiveMeATask run completed. Total time: {timer.Elapsed.TotalSeconds} seconds.");
// Second Run:
// -------------------------
Console.WriteLine("-------------------------------");
Console.WriteLine("Running AwaitATask in parallel...");
timer.Restart();
Parallel.For(0, 500, (i) =>
{
SillyClass.AwaitATask().Wait();
});
timer.Stop();
Console.WriteLine($"AwaitATask run completed. Total time: {timer.Elapsed.TotalSeconds} seconds.");
Console.ReadLine();
}
}
public class SillyClass
{
public static TimeSpan SomeTime = TimeSpan.FromSeconds(3);
public static Task GiveMeATask()
{
return Task.Delay(SomeTime);
}
public static async Task AwaitATask()
{
await Task.Delay(SomeTime);
}
}
}
It is also available as a Gist.
SillyClass has two methods which both return a Task. Inside both methods I have a Task.Delay of 3 seconds to simulate an expensive network or IO bound operation.
The first method GiveMeATask simply returns the task from Task.Delay. The second method AwaitATask awaits the Task.Delay with the async/await keywords.
Both methods get called from Parallel.For to simulate concurrent calls.
What I found interesting is that the first run always takes about double the time as the second run, no matter how many times I repeat it:
As far as I understand the async/await pattern has to capture a synchronisation context, which adds a little bit of overhead, but I would be surprised if that is the reason?
I also understand that in certain applications such as a WPF application or an ASP.NET application where only 1 thread can access the UI/Request context an synchronously blocking .Wait() can cause deadlocks, but this is not the case for console applications and evidently I don't have a deadlock here, because both runs complete just fine.
So I am clearly not understanding the full picture of the above and would appreciate someone who can shed more light on this?

Categories