Hello How make method MethodA start new execution only when finished previous execution?
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
MethodB();
MethodC();
}
public static void MethodA ()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public static void MethodB()
{
Task.Run(() => MethodA());
}
public static void MethodC()
{
Task.Run(() => MethodA());
}
}
In this case I have this result
Hello World
Start
Start
Stop
Stop
But I need something like this
Hello World
Start
Stop
Start
Stop
The simplest way is to create a static locking object and reference that in MethodA:
private static readonly object _methodALockObject = new object();
public static void MethodA()
{
lock(_methodALockObject)
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
}
Try to use async and await:
public static void Main()
{
Task.Run(async () =>
{
await MethodB();
await MethodC();
}).GetAwaiter().GetResult();
}
public static void MethodA()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public async static Task MethodB()
{
await Task.Run(() => MethodA());
}
public async static Task MethodC()
{
await Task.Run(() => MethodA());
}
async and await keywords help to make your asynchronous code to be executed in syncronous order.
Related
public class Program
{
public static void Main(string[] args)
{
Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}
The above code returning below out
Method1 - Start
Method1 - End
Method2 - Start
Method2 - End
I want an output like
Method1 - Start
Method2 - Start
Method1 - End
Method2 - End
how to achieve that basically how to run async methods in parallel
Option A - with Task.Delay
public class Program
{
public static async Task Main()
{
await Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
Console.WriteLine("Method1 - Start");
await Task.Delay(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
Console.WriteLine("Method2 - Start");
await Task.Delay(1000);
Console.WriteLine("Method2 - End");
}
}
Option B - with Task.Run
public class Program
{
public static async Task Main()
{
await Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = Task.Run(() => method1());
var m2 = Task.Run(() => method2());
await Task.WhenAll(m1, m2);
}
private static void method1()
{
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static void method2()
{
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}
Or you can use Task.Yield().
public class Program
{
public static void Main(string[] args)
{
Start();
Console.ReadLine();
}
private static async Task Start()
{
var m1 = method1();
var m2 = method2();
await Task.WhenAll(m1, m2);
}
private static async Task method1()
{
await Task.Yield();
Console.WriteLine("Method1 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method1 - End");
}
private static async Task method2()
{
await Task.Yield();
Console.WriteLine("Method2 - Start");
Thread.Sleep(1000);
Console.WriteLine("Method2 - End");
}
}
This one is a bit "more parallel" than using Task.Delay() because it immediately yields back an uncomplete task, but with delay the "asynchronicity" only happens when you reach that line of code. If you have long running sync code before the delay, that will delay the execution of subsequent methods (in this case method2).
Edit
a more detailed explanation on When would I use Task.Yield()?
As you can see above, it does a debugger unhandled exception with nothing catching it at the end.
I have an AppDomain Crash Logger set inside of Program that works for everything outside of the await foreachasync() call.
Is there something im missing?
ForEachAsync:
public static class Extensions
{
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition) {
while (partition.MoveNext()) {
await body(partition.Current);
}
}
}));
}
}
Example:
//Call this in Program or early on in code
UnhandledExceptionLogger.Initialize();
//Call this, Nothing gets caught in the handler
async public void throwException() {
await Extensions.ForEachAsync(source, 10, combo => {
return Task.Run(() => {
throw new IOException();
}
}
}
//Whereas if I call this, it does
public void throwExceptionSynchronous() {
throw new IOException();
}
static class UnhandledExceptionLogger {
public static void Initialize() {
AppDomain.CurrentDomain.UnhandledException += _CurrentDomain_UnhandledException;
}
static void _CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
if (e.IsTerminating) {
MessageBox.Show("UNHANDLED EXCEPTION CAUGHT!\n" + e.ExceptionObject.ToString());
Environment.Exit(1);
}
}
}
For the sake of simplicity I reproduced my Xamarin nUnit testing error as a console aplication and it shows the same problem that I cannot understand. So first the code that works and second the code that doesn't work.
Simple console app
public class Working
{
private MyViewModel _viewModel;
public Working()
{
Console.WriteLine("Start");
_viewModel = new MyViewModel();
}
static void Main(string[] args)
{
Working prog = new Working();
prog.Print();
}
public void Print()
{
_viewModel.NewSurveyCommand.Execute(null);
}
}
public class MyViewModel
{
public MyViewModel()
{
NewSurveyCommand = new MyCommand(RunTest);
}
public ICommand NewSurveyCommand { get; private set; }
private void RunTest()
{
Console.WriteLine("Running...");
Thread.Sleep(1000);
Console.WriteLine("Test done");
}
}
public class MyCommand : ICommand
{
private Action _action;
public MyCommand(Action action)
{
_action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action.Invoke();
}
}
This works fine, the console prints running... then prints test done in one second. Now the second async version which only prints running...
public class Program
{
private ViewModel _viewModel;
public Program()
{
Console.WriteLine("Start");
_viewModel = new ViewModel();
}
static void Main(string[] args)
{
Program prog = new Program();
prog.Go();
}
async void Go()
{
await Print();
}
public async Task Print()
{
await Task.Run( () => _viewModel.NewSurveyCommand.Execute(null) );
}
}
public class ViewModel
{
public ViewModel()
{
NewSurveyCommand = new Command(async () => await RunTest());
}
public ICommand NewSurveyCommand { get; private set; }
public async Task RunTest()
{
Console.WriteLine("Running...");
await Task.Run( () => Thread.Sleep(1000));
Console.WriteLine("Test done");
}
}
public class Command : ICommand
{
private Action _action;
public Command(Action action)
{
_action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action.Invoke();
}
}
}
So the second case executes only part of the code, when it gets to await Task.Run( () => Thread.Sleep(1000)); it just leaves the method to never come back. I don't understand why and how to solve that. Has anyone ever come across the same problem. Thanks.
The main thread terminates before Thread.Sleep(1000); has finished and so do all child threads. You can try to add a Thread.Sleep(2000); at the end of your Main method or let it do something else. It should work then. Also have a look at Microsoft's Task class documentation:
Waiting for one or more tasks to complete
Because tasks typically run asynchronously on a thread pool thread, the thread that creates and starts the task continues execution as soon as the task has been instantiated. In some cases, when the calling thread is the main application thread, the app may terminate before any the task actually begins execution. In others, your application's logic may require that the calling thread continue execution only when one or more tasks has completed execution. You can synchronize the execution of the calling thread and the asynchronous tasks it launches by calling a Wait method to wait for one or more tasks to complete.
I hope this helps.
Edit:
You should better use Task.Wait() instead of Thread.Sleep() because often you don't know when a thread will finish:
static void Main(string[] args)
{
Program prog = new Program();
Task t = prog.Print();
t.Wait();
}
This doesn't work because you start a new thread in RunTest(). Then the thread created in Print() returns and unblocks the main thread which returns and terminates every thread. You could solve this by running Thread.Sleep() in RunTest() synchronously. Everything would look like this:
public class Program
{
private ViewModel _viewModel;
public Program()
{
Console.WriteLine("Start");
_viewModel = new ViewModel();
}
static void Main(string[] args)
{
Program prog = new Program();
Task t = prog.Print();
t.Wait();
}
async void Go()
{
await Print();
}
public async Task Print()
{
await Task.Run(() => _viewModel.NewSurveyCommand.Execute(null));
}
}
public class ViewModel
{
public ViewModel()
{
NewSurveyCommand = new Command(() => RunTest());
}
public ICommand NewSurveyCommand { get; private set; }
public void RunTest()
{
Console.WriteLine("Running...");
Thread.Sleep(1000);
Console.WriteLine("Test done");
}
}
public class Command : ICommand
{
private Action _action;
public Command(Action action)
{
_action = action;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_action.Invoke();
}
}
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
here is sample of code for
private void MethodStarter()
{
Task myFirstTask = Task.Factory.StartNew(Method1);
Task mySecondTask = Task.Factory.StartNew(Method1);
}
private void Method1()
{
// your code
}
private void Method2()
{
// your code
}
i am looking for code snippet for Parallel Tasks by which i can do the callback and pass argument to function also. can anyone help.
If I understood your question right this might be the anwser:
private void MethodStarter()
{
Task myFirstTask = Task.Factory.StartNew(() => Method1(5));
Task mySecondTask = Task.Factory.StartNew(() => Method2("Hello"));
}
private void Method1(int someNumber)
{
// your code
}
private void Method2(string someString)
{
// your code
}
If you want to start all the threads at the same time you can use the example given by h1ghfive.
UPDATE:
An example with callback that should work but I haven't tested it.
private void MethodStarter()
{
Action<int> callback = (value) => Console.WriteLine(value);
Task myFirstTask = Task.Factory.StartNew(() => Method1(5, callback));
Task mySecondTask = Task.Factory.StartNew(() => Method2("Hello"));
}
private void Method1(int someNumber, Action<int> intCallback)
{
// your code
intCallback(100); // will call the call back function with the value of 100
}
private void Method2(string someString)
{
// your code
}
You can alos look at Continuation if you don't want to pass in callback functions.
You should try something like this instead :
Parrallel.Invoke(
() => Method1(yourString1),
() => Method2(youString2));