0

In modernizing, I'm trying to update legacy libraries to use a client-side WCF service. The following is close to what I need, but I can't figure out how to add the created task to a queue that will only process one request at a time.

[ServiceContract(Name="MyService", SessionMode=Session.Required]
public interface IMyServiceContract
{
    [OperationContract()]
    Task<string> ExecuteRequestAsync(Action action);
}

public class MyService: IMyServiceContract
{
    // How do I get this piece in a task queue?
    public async Task<string> ExecuteRequestAsync(Request request)
    {
        return await Task.Factory.StartNew(() => request.Execute();)
    }
}

I've looked at TaskQueue's that Servy shared (Best way in .NET to manage queue of tasks on a separate (single) thread). But, I'm having trouble combining the two into something that works. When I attempt to add my task to the TaskQueue below, the task never runs. I know I'm missing something, so any help is greatly appreciated.

public class TaskQueue
{
    private SemaphoreSlim semaphore;
public TaskQueue()
    {
        semaphore = new SemaphoreSlim(1);
    }

    public async Task<T> Enqueue<T>(Func<Task<T>> taskGenerator)
    {
        await semaphore.WaitAsync();
        try
        {
            return await taskGenerator();
        }
        finally
        {
            semaphore.Release();
        }
    }
    public async Task Enqueue(Func<Task> taskGenerator)
    {
        await semaphore.WaitAsync();
        try
        {
            await taskGenerator();
        }
        finally
        {
            semaphore.Release();
        }
    }
}

Thanks

  • Is there any log information? If possible, print out the log to see what errors are reported. – Jiayao Aug 18 '22 at 08:43
  • The log was giving a InvalidOperationException due to two (or more) requests executing at the same time. When they both tried to run, they'd basically try to kill each other. I just needed to work out how to get the TaskQueue working, and I think I have that working now. Thanks – VaultBoy13 Aug 19 '22 at 01:42

1 Answers1

-1

I ended up adding to the TaskQueue:

Task<T> Enqueue<T>(Func<T> function)
{
    await semaphore.WaitAsync();
    try
    {
        return await Task.Factory.StartNew(() => function.invoke();)
    }
    finally
    {
        semaphore.Release();
    }
}

And, update the host to the following:

return await queue.Enqueue(request.Execute();)

And, this is doing what I need from the WCF service. The items execute FIFO from multiple applications sending requests.

  • [CA2008: Do not create tasks without passing a TaskScheduler](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2008). Prefer `Task.Run` over `Task.Factory.StartNew`. – Theodor Zoulias Aug 19 '22 at 01:52
  • 1
    Thanks. I wasn't aware. I'll make updates to my code. – VaultBoy13 Aug 23 '22 at 20:40