Answer the question
In order to leave comments, you need to log in
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. 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>
... Answer the question
In order to leave comments, you need to log in
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 questionAsk a Question
731 491 924 answers to any question