C# Async recursive function not working properly? [duplicate] - c#

This question already has answers here:
async/await - when to return a Task vs void?
(6 answers)
Closed 2 years ago.
This is my code :
class Program
{
static void Main(string[] args)
{
update();
}
static async void update()
{
await Task.Delay(100);
Console.WriteLine("X");
update();
}
}
Console never outputs any text at all, and I have no clue why. What am I doing wrong?

Your Main method is not async, so it doesn't wait for your update method. Also, your update method should return a Task so your Main method can await it.
static async Task Main(string[] args)
{
await update();
}
static async Task update()
{
await Task.Delay(100);
Console.WriteLine("X");
await update();
}

Related

Wait for a specific result from Task then run another method in C#

I have a WPF app running on .net 6 and an external device connected to it.
Initializing the device sometimes fails and I don't want to hold the UI thread trying to initialize it.
I want to run the following method (_device.Init()) in an async fashion and when it returns true, run Start() method.
edit: run it until it returns true from the _device.Init() method, not true for finishing the task
Is there a built-in functionality to do it with tasks? or any other "best practice" way?
Thank you :)
SomeDevice _device = new();
public async void Init()
{
// some other code
while (Task.Run(() => _device.Init()).Result == false)
{
}
Start();
}
public void Start()
{
// some other code
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
_device.Start();
}));
}
Instead of getting the Result of the Task (which may block the UI thread) you should await the Task:
public async void Init()
{
// some other code
while (!await Task.Run(() => _device.Init()))
{
}
Start();
}
The method should also be awaitable and be awaited when called, e.g. in an async Loaded event handler:
public async Task Init()
{
// some other code
while (!await Task.Run(() => _device.Init()))
{
}
Start();
}
...
await Init();
public async void Init()
{
var task = _device.Init();
//do work here
await task;
Start();
}
Should do the trick, it'll do the work and then wait for the task to complete before going to Start();
If you want to simply wait for init to finish and then run start it's even simpler with
await _device.Init().ContinueWith((x) => { Start();})

Right method to loop trough Task.Run in C#

I would like to know if there 'right' method to loop one task forever?
What I've tried:
private static void A()
{
Task.Run(B);
}
private static async Task B()
{
while (true)
{
Task Delay = Task.Delay(10000);
await C();
await Delay;
}
}
private static async Task C()
{
// some async code that will work every 10s
}
It is working, but I want to understand is there any better options to do the same.
Thanks in advance.

Calling void async equals Task.Run? [duplicate]

This question already has answers here:
Do you have to put Task.Run in a method to make it async?
(3 answers)
Closed 1 year ago.
When I call an async method which returns void, is it the same as when I invoke it with the Task.Run method? I ask because in the doc of the FileSystemWatcher they mention the following.
Keep your event handling code as short as possible.
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-5.0#events-and-buffer-sizes
So I want to leave the scope of the event method very fast. Or do they mean something different?
Snippet of my code for better understanding.
private void OnCreated(object sender, FileSystemEventArgs e)
{
RunSaveWithLogger(AddLocation, e.FullPath);
}
private async void RunSaveWithLogger(Func<string, Task> func, string fullPath)
{
Edit:
After reading your answers and comments, I changed my code to this.
private void OnCreated(object sender, FileSystemEventArgs e)
{
Task.Run(() =>
{
RunSaveWithLogger(AddLocation, e.FullPath);
});
}
private async void RunSaveWithLogger(Func<string, Task> func, string fullPath)
{
try
{
await func.Invoke(fullPath);
}
catch (Exception exception)
{
_logger.LogError(exception, "");
}
}
Thanks for your time and help, I really appreciate that.
simple answer No! they are not the same. for instance, in the example below, "Task.Run" creates a new thread and so, runs every code within it in a new thread, while "async void" doesn't. (I doubt if this is the answer you are looking for though).
using System;
using System.Threading.Tasks;
class Solution
{
static void Main(string[] args)
{
async void Method1()
{
while (true)
{
}
}
Task.Run(() => {
while (true)
{
}
});
Console.WriteLine("This will print");
Method1();
Console.WriteLine("This won't");
}
}

How to avoid OutOfMemoryException when using Task.Run()? [duplicate]

This question already has answers here:
async/await - when to return a Task vs void?
(6 answers)
Closed 2 years ago.
I get OutOfMemoryException when I call this method on startup. StartSignalR method should run a Task which calls Update() method every second.
public void StartSignalR()
{
Task t = Task.Run(() =>
{
try
{
bool push = true;
while (push)
{
Update();
}
}
catch (System.Exception ex)
{
LogManager.LogError(ex);
}
});
}
I use Task.Delay in Update()
private async static void Update()
{
await Task.Delay(1000);
Updater.MPrice();
}
To make your Task.Delay actually wait, you have to declare your lambda as async and await the Update method.
public void StartSignalR()
{
//added async
Task t = Task.Run(async () =>
{
try
{
bool push = true;
while (push)
{
//await the Update method
await Update();
}
}
catch (System.Exception ex)
{
LogManager.LogError(ex);
}
});
}
With this change your Update method has to return a Task
//changed signature
private async static Task Update()
Chances are good that this should reduce the memory footprint, because currently you are firing the Update method like crazy.

How to use async to execute callback delegate

I have a callback function which needs to takes several seconds to process and should be a async method, but I can't find a way to execute this async callback by await because it must be a Delegate param in the calling method.
Here is some piece of code:
async Task Callback(){//do some callback..}
async Task DoSomething(Func<Task> callback){//I want to execute the callback like: await callback();}
async void Main(){ DoSomething(Callback);}
Sorry for my poor english, any idea to do that? Thanks!
You will have to await first call itself.
change
async void Main(){ DoSomething(Callback);}
to
async void Main(){ await DoSomething(Callback);}
After that It should work, I tested with your sample code. Please verify at your end.
class Program
{
static void Main(string[] args)
{
(new Test()).Main();
Console.ReadKey();
}
}
public class Test
{
async Task Callback()
{
Console.WriteLine("I'm in callback");
}
async Task DoSomething(Func<Task> callback)
{
Console.WriteLine("I'm in DoSomething");
await callback();
}
public async void Main()
{
Console.WriteLine("I'm in Main");
await DoSomething(Callback);
Console.WriteLine("Execution completed");
}
}
Here is output

Categories