The87Boy
The87Boy

Reputation: 887

Multiple async call

I need to create multiple async calls like

IList<Task> Ts = new List<Task>();
Ts.Add(GetInformationFromServer(ID));

But I do not what do await in the thread, I am calling from

So it should be possible to do like this (one of the old ways, but are there a new one?), from another call

GetInformation(string ID) {
   while (!Finish) {
      Thread.Sleep(100);
   }
   return _Information.First(a=>a.ID==ID);
 }

I could of course save the Tasks in a variable, but how can I start them? And how do I get the status?
I think I can await them in another thread, but how can I check if they are finish? Should I implement it on my own?
And how do I start them (should I just use Task.WhenAll without await)?

UPDATE

I figured out, I have to implement my own way, so the answer is kind of this way, but I need to use Task instead of Func

/// The executed elements
private IList<T> _ExecutedElements;

/// The Stack over the elements to be executed
private Stack<T> _ExecutingElements;

/// The method to be runned
private Func<object, Task<T>> _Method;

/// Should the while-loop start?
private bool _Running;

/// The Task
private Task<T> _Task;

/// Construct the class
/// <param name="Method">The function to be executed</param>
public MultiAsync(Func<object, T> Method) {
   _Method = Method;
}

/// Add an element
/// <param name="Item">The item to be added</param>
public void AddItem(T Element) {
   _ExecutingElements.Push(Element);
}

/// Execute the method
public async void ExecuteAsync() {

   // Set it to start running
   _Running = true;

   // While there are elements left
   while (_ExecutingElements.Count > 0) {

      // Check if it is not running, and if it isn't break out
      if (!_Running) { break; }

      // The current element
      T Element = default(T);

      // Pop out the element, that has not been runned through
      do { Element = _ExecutingElements.Pop(); }
      while (!_ExecutedElements.Contains(Element));

      // Check if there is an element, and if there is execute the method and await it
      if (Element != default(T)) {
         await ExecuteMethodAsync(Element);
      }
   }
}

/// Execute the item
/// <param name="Item">The item to be executed</param>
/// <returns>The executed item (due to reflection in FillInformation, the Item is filled)</returns>
public async Task<T> ExecuteItemAsync(T Item) {

   // Check if the item has not been executed, and if it is not executed
   if (!_ExecutedElements.Contains(Item)) {

      // Stop the while-loop
      _Running = false;

      // Check if the Task is running, and if it is await it
      if (_Task != default(Task) && !_Task.IsCompleted && !_Task.IsFaulted) {
         await _Task;
      }

      // Execute the method using the specific item
      await ExecuteMethodAsync(Item);
   }

   // Start the while-loop
   ExecuteAsync();

   // Return the element
   return Item;
}

/// Execute the method
/// <param name="Item">The item to run</param>
/// <returns>The Task to be executed</returns>
private async Task ExecuteMethodAsync(T Item) {

   // Set the Task
   _Task = _Method.Invoke(Item)

   // Start the task
   T Element = await _Task;

   // Add the item to the List
   _ExecutedElements.Add(Element);

   // Fill the information
   FillInformation(Element);
}

The call is like this

private async void FillTasksAsync(IEnumerable<Model.Task> Tasks) {
   _InfoLoader = new MultiAsync<Model.Task>(Tsk => { return GetTaskAsync(Tsk); });

   foreach (var Tsk in Tasks) {
      _InfoLoader.AddItem(Tsk);
   }
}

Upvotes: 0

Views: 961

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456322

I have a blog post that discusses asynchronous initialization, which sounds like what you need. It's derived from an original idea by Stephen Toub.

In this case, you could use:

List<AsyncLazy<string>> Ts = ...
Ts.Add(new AsyncLazy<string>(() => GetServerStringAsync(ID));

To start one downloading, you can do:

Ts[0].Start();

And when you need it, you can do:

var result = await Ts[0];

which will (asynchronously) wait for it to finish downloading if it hasn't already. If it has already, then you'll get the result immediately.

Upvotes: 1

Related Questions