0

I'm building my own queue based system but so far I have a small problem: How can I add an async Task to another function to process it?

My processor function works like this:

  • I have a Queue object:

    public class Queue
    {
     public string Id;
    
     public CancellationTokenSource Cts;
    
     public Task Task;
    
     public Queue(Task task, string id, CancellationTokenSource cts)
     {
        Id = id;
        Cts = cts;
        Task = task;
     }}
    

And a command to add my tasks to 2 Lists: List<Queue> ActiveQueues and List<Queue> Queued

The ActiveQueues is a list with all the active queues, and Queued is a list with all queues.

My Add function looks like this:

public async Task Add(Task task, string id, CancellationTokenSource cts)
{
    var queue = new Queue(task, id, cts);
    if (ActiveQueues.Count < MainWindow.appConfig.MaxAsyncSessions)
    {
        var exists = ActiveQueues.Find(q => q.Id == queue.Id);
        if (exists == null) // I don't want 2 queues with the same id to run at once so I add it to the queued list that's processed by another function.
        {
            ActiveQueues.Add(queue);
            ActiveQueueIds.Add(queue.Id);
            await queue.Task;
        }
        else
        {
            Queued.Add(queue);
        }
    }
    else
    {
            Queued.Add(queue);
    }
}

The problem is that my task also has parameters so using it like queue.Add(AsyncFunction(param1, param2), "idExample", new CancellationTokenSource()) triggers the function before adding it to the ActiveQueues list.

What would be the correct way to do what I want to do right now?

5
  • What problem is caused by triggering the Task before adding it to the queue? Commented Jun 5, 2020 at 14:49
  • Not related to your main question, but you can clarify your "exist"-check by using IEnumerable.Any(), which returns a bool instead of null or an object. Commented Jun 5, 2020 at 14:54
  • As a side note, there is already a Queue class in BCL, so giving the same name to a custom class with completely different semantics can create confusion. Commented Jun 5, 2020 at 15:56
  • @CGundlach Yeah, I've changed it in the meantime:) Got confused with what triggers my second function when it should have been placed in the queued list. Commented Jun 5, 2020 at 19:45
  • @TheodorZoulias I haven't noticed that thanks. But since only me and the customer has the code shouldn't be so confusing. Commented Jun 5, 2020 at 19:46

1 Answer 1

4

Change your Add method signature to accept delegate:

public async Task Add(Func<Task> taskFactory, string id, CancellationTokenSource cts)

And either change Queue ctor accordingly and introduce method like Start which will start task (basically calling taskFactory()) and optionally having validation if it is already started and caching result of taskFactory() or use Lasy<> for handling it.

Simple implementation using Lazy can look like this (some code omitted for brevity):

class Queue
{
    public Lazy<Task> Task;
    public Queue(Func<Task> taskFactory)
    {
        Task = new Lazy<Task>(taskFactory);
    }
}

// in your Add method:    
var queue = new Queue(taskFactory);
await queue.Task.Value;

// Add call:
q.Add(() => AsyncFunction(param1, param2), "idExample", new CancellationTokenSource())
Sign up to request clarification or add additional context in comments.

3 Comments

This can't be called with parameters for the Func, as OP requires.
@JohnathanBarclay Add(() => asynmethod(param1, pram2), ....), the problem is about triggering task as far as i understand?
Yes, so far the problem is that the task is triggered before calling it in the Add function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.