I
I
Ilya2014-01-17 14:27:27
.NET
Ilya, 2014-01-17 14:27:27

How to pass an arbitrary method to a class for asynchronous execution, tracking the status and getting the result?

Hello dear community.
Short introductory part
Now I write small WCF Restful service, there was a task to execute long requests. The simplest and most understandable solution was to accept such requests for processing, issuing the job number and the corresponding status. Then the client addresses the task number at another address with the number and receives his answer (if it is already ready). The idea is not new, obvious and has been confirmed by searches:
- billhiggins.us/blog/2011/04/27/resty-long-ops (very well described)
- lostechies.com/jimmybogard/2013/05/15/eventual-con. ..
what I tried to do
Remembering that I wrote something similar about a year ago, I looked at the code archives. It turned out that at that time I only needed to execute one long method, so I solved everything quickly and simply (I suspect that it is far from ideal, but it works) - the long method was wrapped in a class like this:

using System;
using System.ComponentModel;
namespace Service
{
    public class LongTermJob
    {
  public string JobId { get; private set; }
        public bool IsCompleted
        {
            get { return !_worker.IsBusy; }
        }
        public string Result
        {
            get { return IsCompleted ? _result : null; }
        }
        private readonly BackgroundWorker _worker;
        // Результаты выполнения, вместо string нужный тип.
        private string _result;
        public LongTermJob(string jobId, WorkerArgs args)
        {
      JobId = jobId;
            _worker = new BackgroundWorker();
            _worker.DoWork += _worker_DoWork;
            _worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
            _worker.RunWorkerAsync(args);
        }
        private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            _result = "Результат выполнения метода";
        }
        private void _worker_DoWork(object sender, DoWorkEventArgs e)
        {
            var user = (WorkerArgs) e.Argument;
            Console.WriteLine("Name: {0} Age: {1}", user.Name, user.Age);
        }
    }
    public class WorkerArgs
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}
The query parameters were accepted, placed in WorkerArgs, JobId was assigned (which was then returned), a LongTermJob instance was created and simply placed in a List<>. Then, when accessed, the status of the task was checked and, if necessary, the result was returned. For that case, it was convenient, even the percentage of completion, if necessary, can be issued.
But this time the code doesn't work. It is required to execute indefinitely not one, but dozens of very different methods that return a variety of types and have an arbitrary number of parameters.
I started reading and trying options with:
- delegates, but they only allow you to pass specific parameters and return one type;
- Tasks, but you still need to transfer the method to it somehow;
- Funcs to pass them to Tasks, but they have overloads for each number of parameters, how to pass an arbitrary one.
Basically, I tried everything I could. Now it will stop at something like this code:
public class LongTermJob
    {
        public bool IsCompleted
        {
            get { return _task.IsCompleted; }
        }
        public TestClass Result
        {
            get { return IsCompleted ? _result : null; }
        }
        private readonly Task<TestClass> _task;
        private readonly TestClass _result;
        public LongTermJob(Func<TestClass> method)
        {
            _task = Task.Factory.StartNew((method));
            _result = _task.Result;
        }
    }
    public class WorkerArgs
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
If there was such a code, but for TestClass to be <T>...
Perhaps, we need to approach it from a completely different angle, or there are already ready-made solutions for such situations. I would be grateful for any solution and suggestion.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vadim Martynov, 2014-01-17
@Gorily

Perhaps by the time I get to your question, someone else will remember the industrial solution.
I used this method to unify function signatures:
habrahabr.ru/post/143465
That is, any function with N parameters can be converted to TResult Method () using currying / partial application. Among the shortcomings - the FunctionalExtensions class contained about a dozen methods for a different number of parameters, resulting in a different number of parameters. It is more convenient for you - you need to bring functions with a different number of parameters to one form - functions without parameters.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question