2

I am trying to build a WCF service that -

  1. Is single instance
  2. Allows clients to make multiple request to functions (eg. StartJob)
  3. StarJob(request) 'queues' the request to the TaskFactory (one instance) running on Concurrent task schedule (implemented as per example

  4. As tasks in the task factory are completed, the response is returned

  5. While a task is running and more requests come in, they get queued (provide max concurrent number is reached)

Objective is to build a system that accepts requests from clients and queues them for processing.

Currently, my code (shown below), runs all requests simultaneously without taking the max concurrent number of task scheduler into account.

Questions

  1. What am I missing out?
  2. Any good example/reference I can look at? (I am sure this is not an uncommon use case)

Code

IService

[ServiceContract]
public interface ISupportService
{
    [OperationContract]
    Task<TaskResponse> StartTask(TaskRequest taskRequest);
}

Service

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class SupportService : ISupportService
{
    private static TaskRequestHandler taskRequestHandler;

    public SupportService()
    {        
        taskRequestHandler = TaskRequestHandler.GetInstance();         
    }

    public Task<TaskResponse> StartTask(TaskRequest taskRequest)
    {
        var tcs = new TaskCompletionSource<TaskResponse>();

        if (!IsTaskRequestValid(taskRequest))
            tcs.SetResult(new TaskResponse()});

        taskRequestHandler.StartTaskAsync(taskRequest, lockHandler).ContinueWith(task => { tcs.SetResult(task.Result); });

        return tcs.Task;
    }    
}

TaskRequestHandler

public class TaskRequestHandler
{
    private ConcurrentTaskScheduler taskScheduler;
    private TaskFactory taskFactory;

    private TaskRequestHandler()
    {
        taskScheduler = new ConcurrentTaskScheduler(2);
        taskFactory = new TaskFactory(taskScheduler);
    }

    private Task<TaskResponse> StartTaskAsync (TaskRequest request, LockHandler lockHandler)
    {
        var tcs = new TaskCompletionSource<TaskResponse>();
        taskFactory.StartNew(() =>
        {
            //Some task with tcs.SetResults()
        });

        return tcs.Task;
    }
}
  • This question can help you about the queueing and concurrence: http://stackoverflow.com/questions/7122608/wcf-concurrencymode-single-and-instancecontextmode-percall/7149683#7149683 – Ricardo Pontual Aug 04 '16 at 11:12

1 Answers1

0

Aaaah! A big miss on my part. The action executed in taskFactory was completing before I expected it to. As such, all the tasks appeared to be running in parallel.

I updated the action code to monitor the action completion correctly and raising correct callbacks, the above code worked fine.

However, made a minor change -

  • There is not need for StartTask(TaskRequest taskRequest) to return a Task. Rather, just returning the TaskResponse will suffice (as WCF takes care of Async and Sync functionality of every OperationContract)