In the code below I need to execute the three Get... methods in parallel. When a Get... method completes I need to immediately call the Save... method. Note Save... takes thing as a parameter.
All Get and Save methods must complete before DoStuffAsync returns.
My guess is that I need a continuation on the Get... methods but I dont know how to construct it.
protected async void DoStuffAsync()
{
SomeThing thing = new SomeThing { ID = 5 };
SomeRepository rep = new SomeRepository();
// We need to run all three Get... methods in parallel
// As soon as a Get... method completes we need to save the result to the correct property on thing and call the Save... method .
var getRed = rep.GetRedAsync().ContinueWith<Task<string>>(async x => { thing.Color1 = x.Result; await rep.SaveRedAsync(thing); return x; }); // does not compile
var getBlue = rep.GetBlueAsync();
var getGreen = rep.GetGreenAsync();
string red = await getRed.Result; // this is not good because getBlue may finish before getRed. We want dont want to wait on getRed before calling SaveBlue
await rep.SaveRedAsync(thing);
var b = await getBlue;
var c = await getGreen;
// thing must be fully initialized before DoStuffAsync returns
}
public class SomeThing
{
public int ID { get; set; }
public string Color1 { get; set; }
public string Color2 { get; set; }
public string Color3 { get; set; }
}
public class SomeRepository
{
public async Task<string> GetRedAsync()
{
return await Task.Run(() => "red");
}
public async Task<string> GetBlueAsync()
{
return await Task.Run(() => "blue");
}
public async Task<string> GetGreenAsync()
{
return await Task.Run(() => "green");
}
public async Task SaveRedAsync(SomeThing thing)
{
// We need thing.ID here as well as other properties
await Task.Delay(1);
}
public async Task SaveBlueAsync(SomeThing thing)
{
await Task.Delay(1);
}
public async Task SaveGreenAsync(SomeThing thing)
{
await Task.Delay(1);
}
}
Well, you could explicitly use ContinueWith - or you could break off each "get and save" into a separate async method or async lambda. For example:
async Task GetAndSaveRedAsync(SomeThing thing, SomeRepository rep)
{
var red = await rep.GetRedAsync();
thing.Red = red;
await SaveRedAsync(red);
// Return red if you want (change the return type to Task<string>)
}
// Ditto for the others
Then:
protected async void DoStuffAsync()
{
SomeThing thing = new SomeThing { ID = 5 };
SomeRepository rep = new SomeRepository();
var handleRed = GetAndSaveRedAsync(thing, rep);
var handleBlue = GetAndSaveBlueAsync(thing, rep);
var handleYellow = GetAndSaveYellowAsync(thing, rep);
// Or use Task.WhenAll
await handleRed;
await handleBlue;
await handleYellow;
}
I would not mix ContinueWith and await and rather use an async lambda directly:
protected async Task DoStuffAsync()
{
SomeThing thing = new SomeThing { ID = 5 };
SomeRepository rep = new SomeRepository();
// We need to run all three Get... methods in parallel
// As soon as a Get... method completes we need to save the result to the correct property on thing and call the Save... method .
Func<Task<X>> getRedFunc = async() =>
{
var result = await rep.GetRedAsync();
thing.Color1 = result;
await rep.SaveRedAsync(thing);
return result;
};
var getRed = getRedFunc();
var getBlue = rep.GetBlueAsync();
var getGreen = rep.GetGreenAsync();
await Task.WhenAll(getRed, getBlue, getGreen);
}
Also, don't use async void methods for anything but event handlers. You won't be able to observe the completion of a method like this or handle exceptions possibly thrown inside it.
You can try parallel framework:
using System.Threading;
using System.Threading.Tasks;
Func<Task<string>>[] functions = { rep.GetRedAsync, rep.GetBlueAsync, rep.GetGreenAsync };
Var[] GetArray = new Var[functions.Length]
int i=0;
Parallel.ForEach (var function in functions)
{
GetArray[i++]=function();
}
Note: Require .Net 4
Related
Recently I want to implement a health check for a list of service calls. They are all async task (e.g. Task<IHttpOperationResponse<XXX_Model>> method_name(...)
I would like to put all of them into a list. I followed the answer of this post: Storing a list of methods in C# However, they are async methods.
I put it like this:
a collection of async method
List<Action> _functions = new List<Action> {
() => accountDetailsServiceProvider.GetEmployer(EmployerId),
() => accountServiceProvider.GetAccountStatus(EmployerId)
}
Can someone direct me to the right way to implement putting async methods in to a list and invoke them iteratively?
Thanks in advance!
First, you need to make your methods async. That means they must return a Task. For example:
public static async Task Foo()
{
await Task.Delay(1);
Console.WriteLine("Foo!");
}
public static async Task Bar()
{
await Task.Delay(1);
Console.WriteLine("Bar!");
}
Then to put them in a list, you must define the list as containing the right type. Since an async method actually returns something, it's a Func, not an action. It returns a Task.
var actions = new List<Func<Task>>
{
Foo, Bar
};
To invoke them, Select over the list (using Linq) to invoke them. This creates a list of Tasks in place of the list of Funcs.
var tasks = actions.Select( x => x() );
Then just await them:
await Task.WhenAll(tasks);
Full example:
public static async Task MainAsync()
{
var actions = new List<Func<Task>>
{
Foo, Bar
};
var tasks = actions.Select( x => x() );
await Task.WhenAll(tasks);
}
Output:
Foo!
Bar!
Example on DotNetFiddle
If your methods return a Boolean value, then the return type becomes Task<bool> and the rest follows suit:
public static async Task<bool> Foo()
{
await Task.Delay(1);
Console.WriteLine("Foo!");
return true;
}
public static async Task<bool> Bar()
{
await Task.Delay(1);
Console.WriteLine("Bar!");
return true;
}
var actions = new List<Func<Task<bool>>>
{
Foo, Bar
};
var tasks = actions.Select( x => x() );
await Task.WhenAll(tasks);
After you have awaited them, you can convert the tasks to their results with one more LINQ statement:
List<bool> results = tasks.Select( task => task.Result ).ToList();
I think you are just looking for something simple like this?
var myList = new List<Action>()
{
async() => { await Foo.GetBarAsync(); },
...
};
I would recommend you to change the type from Action to Func<Task> like so instead.
var myList = new List<Func<Task>>()
{
async() => { await Foo.GetBarAsync(); },
};
You can read more about why here: https://blogs.msdn.microsoft.com/pfxteam/2012/02/08/potential-pitfalls-to-avoid-when-passing-around-async-lambdas/
To invoke (simplified)
foreach (var action in myList)
{
await action.Invoke();
}
Based on the comments:
However, my task requires a boolean value for each method call,
because I have to report the status to the frontend whether the
service is down or not
Create a wrapper method for the method which will return required boolean value
public async Task<Result> Check(string name, Func<Task> execute)
{
try
{
await execute();
return new Result(name, true, string.Empty);
}
catch (Exception ex)
{
return new Result(name, false, ex.Message);
}
}
public class Result
{
public string Name { get; }
public bool Success { get; }
public string Message { get; }
public Result(string name, bool success, string message)
=> (Name, Success, Message) = (name, success, message);
}
Then you don't need to have collection of delegates, instead you will have collection of Task.
var tasks = new[]
{
Check(nameof(details.GetEmployer), () => details.GetEmployer(Id)),
Check(nameof(accounts.GetAccountStatus), () => accounts.GetAccountStatus(Id)),
};
var completed = await Task.WhenAll(tasks);
foreach (var task in completed)
{
Console.WriteLine($"Task: {task.Name}, Success: {task.Success};");
}
until now I only have small applications, but now I can not handle these classes c# uwp
I want to break the code into several classes, each class will deal with a few parameters. classes will send parameter values to the main page. but when I try to display those parameters, they are always zero, even though the text file appears modified.
i have main page
namespace airflow
{
public sealed partial class MainPage : Page
{
}
public MainPage()
{
}
private async void main_page_Loaded(object sender, RoutedEventArgs e)
{
param_perimetrala read = new param_perimetrala();
ora_start_perimetrala = read.start_perimetrala;
var mesaj = new MessageDialog(ora_start_perimetrala.ToString());
var res = await mesaj.ShowAsync();
}
}
and a class
namespace airflow
{
public class param_perimetrala
{
public static int ora_start_perimetrala;
public int minut_start_perimetrala;
public int ora_stop_perimetrala;
public int minut_stop_perimetrala;
public int ore_ciclu_perimetrala;
public int minut_ciclu_perimetrala;
public int contor_ore_perimetrala = 0;
public int contor_minute_perimetrala = 0;
public int contor_sec_perimetrala = 0;
public async void readfile_perimetrala()
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile perimetrala_file = await folder.CreateFileAsync("parametrii_perimetrala.txt", CreationCollisionOption.OpenIfExists);
var readFile_perimetrala = await FileIO.ReadLinesAsync(perimetrala_file);
int count = 0;
foreach (var line in readFile_perimetrala)
{
string[] split_perimetrala = line.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
var temp = split_perimetrala[1];
if (count == 0)
{
ora_start_perimetrala = Int32.Parse(temp);
}
if (count == 1)
{
minut_start_perimetrala = Int32.Parse(temp);
}
if (count == 2)
{
ora_stop_perimetrala = Int32.Parse(temp);
}
count = count + 1;
}
}
public int start_perimetrala
{
get { return ora_start_perimetrala; }
set { ora_start_perimetrala = value; }
}
}
}
how to send ora_start_perimetrala value in mainpage?
enter image description here
In your main_page_Loaded event handler method you are calling read_file_perimetrala but read_file_perimetrala is async void. This means as soon as you get to an await statement, and the await is actually awaitable (not returned immediately) then the method will put the rest of the work aside until the awaited portion is complete. Then it picks back up and runs the rest. During that time of placing it aside the calling thread then continues to run wherever it's needed.
You need to make this a Task and await the call to is also so that you can insure the parameters are filled before continuing work.
Change your readFile_perimetrala to be like so:
public async Task readfile_perimetralaAsync()
Change the entire main_page_Loaded event handler to read like so...
private async void main_page_Loaded(object sender)
{
param_perimetrala read = new param_perimetrala();
await read.readfile_perimetralaAsync();
var mesaj = new MessageDialog(read.start_perimetrala.ToString());
var res = await mesaj.ShowAsync();
}
In your code you're assigning the value to a method but I can tell that you want the int value.
Just some light weight examples to help get started understanding Task and async await. Don't use this as a resource but just enough to get you curious to dig deeper because it's a simple but rather deep subject.
public class TaskExamples
{
public async void DoAsyncVoid()
{
await Task.Delay(200);
}
public async Task DoAsyncTask()
{
await Task.Delay(200);
}
public async Task<int> DoReturnValueTask()
{
await Task.Delay(200);
return 50;
}
public async void CallingTasks()
{
DoAsyncVoid(); //This can't use await because it is 'void' so the next line is ran as soon as this command reaches the first 'true awaitable' await.
await DoAsyncTask(); //This runs before DoAsyncVoid is complete.
var value = await DoReturnValueTask(); //This waits until 'DoAsyncTask' is complete because it is a Task and awaited.
await new MessageDialog(value.ToString()).ShowAsync(); //This waits until 'DoReturnValueTask' is complete and value will be 50 in this case.
//All code here waits until the Dialog is closed because it is also awaited.
}
}
I have a simple class that does a synchronous thing,
public static class Synchronous
{
public static void DoTheWholeThing()
{
AStuff aStuff;
using (var a = new A())
{
aStuff = a.GetStuff();
}
BStuff bStuff;
using (var b = new B())
{
bStuff = b.GetStuff();
}
var combination = CombineStuff(aStuff, bStuff);
}
private static Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
Obviously, this code is not fully defined but it does illustrate my question.
Now, the classes A and B are both responsible for retrieving data from different remote sources. Consequently, the developers of A and B have implemented asynchronous entry points called GetStuffAsync which return Task<AStuff> and Task<BStuff> respectively.
I want to take maximum advantage of the asynchronous methods and call them concurrently so I can reduce the overall wait time of my code.
Here is what I've concocted, so far.
public static class Asynchronous
{
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var getAStuffTask = new Func<Task<AStuff>>(
async () =>
{
using (var a = new A())
{
return await a.GetStuffAsync(cancellationToken);
}
})();
var getBStuffTask = new Func<Task<BStuff>>(
async () =>
{
using (var b = new B())
{
return await b.GetStuffAsync(cancellationToken);
}
})();
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
Aside from this code looking curiously like the javascript module pattern, is this the correct approach. I don't think I should be using Task.Run as this code is clearly not CPU bound.
It seems a bit "clunky" that I need to instantiate typed delegates to do this. Is there a better way?
EDIT
following two good answers I'm in a quandary between named functions and continuations.
The code becomes radically simpler when you simply extract the anonymous methods out into named methods:
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var getAStuffTask = GetAStuffAsync(cancellationToken);
var getBStuffTask = GetBStuffAsync(cancellationToken);
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
private static async Task<AStuff> GetAStuffAsync(CancellationToken cancellationToken)
{
using (var a = new A())
{
return await a.GetStuffAsync(cancellationToken);
}
}
private static async Task<BStuff> GetBStuffAsync(CancellationToken cancellationToken)
{
using (var b = new B())
{
return await b.GetStuffAsync(cancellationToken);
}
}
That said, if you really want to stick with the anonymous methods, you can create a helper method that will allow generic type inference and lambdas to implicitly figure out the type of the delegate:
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var getAStuffTask = Start(async () =>
{
using (var a = new A())
{
return await a.GetStuffAsync(cancellationToken);
}
});
var getBStuffTask = Start(async () =>
{
using (var b = new B())
{
return await b.GetStuffAsync(cancellationToken);
}
});
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
public static Task<T> Start<T>(Func<Task<T>> asyncOperation)
{
return asyncOperation();
}
Use TPL continuations to call Dispose as soon as the task is complete.
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
var a = new A();
var b = new B();
// start the tasks and store them for awaiting later
var getAStuffTask = a.GetStuffAsync(cancellationToken);
var getBStuffTask = b.GetStuffAsync(cancellationToken);
// queue up continuations to dispose of the resource as soon as it is not needed
getAStuffTask.ContinueWith(() => a.Dispose());
getBStuffTask.ContinueWith(() => b.Dispose());
// await as normal
var combination = CombineStuff(
await getAStuffTask,
await getBStuffTask);
}
I am unsure if wrapping the whole method in an addition using block will accomplish anything but it may provide peace of mind.
You don't need to wrap your async calls in delegates to get them to execute immediately. If you call the GetStuffAsync methods directly without awaiting them you will have the same result.
public static class Asynchronous
{
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
using (var a = new A())
using (var b = new B()) {
var taskA = a.GetStuffAsync(cancellationToken);
var taskB = b.GetStuffAsync(cancellationToken);
await Task.WhenAll(new [] { taskA, taskB });
var combination = CombineStuff(taskA.Result, taskB.Result);
}
}
private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
Note that this does keep the a and b objects alive during the call to CombineStuff as #Servy notes. If that is a problem the declaration of the Task objects can be moved outside of the using blocks as below:
public static class Asynchronous
{
public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
Task taskA;
Task taskB;
using (var a = new A())
using (var b = new B()) {
taskA = a.GetStuffAsync(cancellationToken);
taskB = b.GetStuffAsync(cancellationToken);
await Task.WhenAll(new [] { taskA, taskB });
}
var combination = CombineStuff(taskA.Result, taskB.Result);
}
private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
{
//// Magic Here
}
}
Although this still holds onto a and b as long as both tasks are running, rather than disposing of each as they return.
I have say an interface called:
interface IExecutor {
String Name { get; }
Task<int> Execute();
}
And two implementations of it (details are irrelevant and you can assume methods are marked with async and work as expected). Each implementation takes between 2-3 seconds to run and there will ever be between 2 and 5 implementations of IExecutor
I have a controller that needs to run all executors and return the results in as ExecutorResult objects. Where ExecutorResult is:
class ExecutorResult {
int Result; // assume usual get n set
String ExecutorName;
}
Ideally this should happen in a Fan-Out approach.
I have thought of the following approaches:
List<Task<int>> tasks = new List<Task<int>>();
foreach(var executor in executors) {
tasks.Add(executor.Execute());
}
var results = Task.WhenAll(tasks);
The problem I have with this approach is that I m not sure if this is best practice in an ASP WebAPI application. Also - given I would like to return Result objects - where Result needs an the name of the executor and the int result from Execute the above solution doesn't work as outside of the for loop I no longer have access to the Name property of each executor.
So what is the best practice for this approach (again - given a Web Api application and not a Console app)
What you have already is a best practice. What you're doing is asynchronous concurrency, which is best done with Task.WhenAll.
Note that the code:
List<Task<int>> tasks = new List<Task<int>>();
foreach(var executor in executors) {
tasks.Add(executor.Execute());
}
var results = Task.WhenAll(tasks);
can be simplified to:
var results = Task.WhenAll(executors.Select(e => e.Execute()));
In spite of the countless examples using List<Task>, you don't actually have to build one up explicitly.
This worked for me:
public class Executor : IExecutor
{
public String Name { get; set;}
public async Task<int> Execute()
{
Console.WriteLine("Executing " + Name);
await Task.Delay(3000);
Console.WriteLine("Finished Executing " + Name);
return 0;
}
}
public async Task<ExecutorResult> Execute(IExecutor executor)
{
return new ExecutorResult { ExecutorName = executor.Name,
Result = await executor.Execute() };
}
public async Task MainAsync()
{
var executors = new List<IExecutor>
{
new Executor { Name = "Executor1" },
new Executor { Name = "Executor2" },
new Executor { Name = "Executor3" }
};
List<Task<ExecutorResult>> tasks = new List<Task<ExecutorResult>>();
foreach(var executor in executors)
{
tasks.Add(Execute(executor));
}
var results = await Task.WhenAll(tasks);
}
void Main()
{
MainAsync().Wait();
}
If I understood it correctly, you're looking for somethng like this:
var tasks = new List<Task<ExecutorResult>>();
foreach (var executor in executors)
{
tasks.Add(((Func<IExecutor, Task<ExecutorResult>>)(
async (e) => new ExecutorResult
{
ExecutorName = e.Name,
Result = await e.Execute()
}))(executor));
}
var results = Task.WhenAll(tasks);
OR, following Stephen Clearly suggestion:
var results = Task.WhenAll(
from executor in executors
select ((Func<IExecutor, Task<ExecutorResult>>)(
async (e) => new ExecutorResult
{
ExecutorName = e.Name,
Result = await e.Execute()
}))(executor))
);
I'm trying to implement the async-await stuff in a (fairly simple) application.
My goal is to update a busyIndicator in between awaits.
I don't know what, but I think I'm missing somehting essential in my understanding of the async await stuff.
private async void StartTest(object obj)
{
try
{
this.IsBusy = true;
this.BusyMessage = "Init..."
await Task.Delay(7000);
var getData1Task = this.blHandler.GetData1Async();
this.BusyMessage = "Retreiving data...";
this.result1 = await getDeviceInfoTask;
this.result2 = await this.blHandler.GetData2Async();
this.BusyMessage = "Searching...";
this.result3 = await this.blHandler.GetData3();
}
finally
{
this.IsBusy = false;
this.BusyMessage = string.empty;
}
}
The busyIndicator has a binding with IsBusy and BusyMessage.
When executing this code, I do get the busyIndicator showing "Init..." but it never changes to "Retreiving data..." or "Searching...".
Even worse: the ui freezes completely while executing the final GetData3.
Most likely GetData1Async, GetData2Async and GetData3 are synchronous methods (that is, I'm guessing that while they do return a Task that they complete all their work synchronously). In that case, the awaits do not suspend the method (since the returned Task will be a completed task). Thus, the method will continue all the way through as one big synchronous method, and the UI will never have a chance to update (since it is not pumping any messages during this time).
If you want more than a guess, show us the code for those three methods.
It sounds like you actually want to execute a synchronous method on a background thread, then asynchronously wait for it to finish in your UI code.
That's exactly what Task.Run() does.
It takes a delegate to run in the ThreadPool, then returns an awaitable Task that give you the result.
Can you please try pushing message by Dispatcher like.
App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
{ this.BusyMessage = "Retreiving data..."; }));
// Do Something
App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
{ this.BusyMessage = "Filtering data..."; }));
// Do Something
Here's a working copy stubbed out with some assumptions on my part. Hope it helps. I tested it in a running WPF app. Note that there is no guarding in what you posted making sure this isn't "double-run" (we can start regardless the value of IsBusy, StartTest should probably ensure that).
public class StackWork : ViewModelBase
{
private class MyHandler
{
private async Task<string> GetDataAsync(string result)
{
return await Task<string>.Run(() =>
{
Thread.Sleep(5000);
return result;
});
}
public async Task<string> GetData1Async()
{
return await GetDataAsync("Data1");
}
public async Task<string> GetData2Async()
{
return await GetDataAsync("Data2");
}
public async Task<string> GetData3()
{
return await GetDataAsync("Data3");
}
}
private bool IsBusy { get; set; }
private string _message = "";
public string BusyMessage
{
get { return _message; }
set { _message = value; RaisePropertyChanged("BusyMessage"); }
}
private MyHandler blHandler = new MyHandler();
private Task<string> getDeviceInfoTask;
private string result1 { get; set; }
private string result2 { get; set; }
private string result3 { get; set; }
public StackWork()
{
getDeviceInfoTask = Task<string>.Run(() =>
{
return ("device info");
});
}
public async void StartTest(object obj)
{
try
{
this.IsBusy = true;
this.BusyMessage = "Init...";
await Task.Delay(7000);
var getData1Task = /*this*/await/*was missing*/ this.blHandler.GetData1Async();
this.BusyMessage = "Retreiving data...";
//assuming this was Task.Run, put that in constructor
this.result1 = getDeviceInfoTask/*this*/.Result/*was missing*/;
this.result2 = await this.blHandler.GetData2Async();
this.BusyMessage = "Searching...";
//This was a little confusing because the name doesn't imply it is
//async, but it is awaited
this.result3 = await this.blHandler.GetData3();
}
finally
{
this.IsBusy = false;
this.BusyMessage = string.Empty;
}
}
}