Reputation: 201
I have the below code which calls a workflow. I am wondering if I can changed the controller to be asynchronous using the async ctp.
public ActionResult Index()
{
var input = new Dictionary<string, object>();
input["ViewData"] = this.ViewData;
var userState = "BeginInvoke example";
var invoker = new WorkflowInvoker(HelloMvcDefinition);
Task workflowTask = Task.Factory.FromAsync<IDictionary<string, object>>(
invoker.BeginInvoke(input, WorkflowCompletedCallback, userState),
invoker.EndInvoke);
workflowTask.Wait();
return View();
}
I have tried this but I cannot seem to get it to work:
public async Task<ActionResult> Index()
{
var input = new Dictionary<string, object>();
input["ViewData"] = this.ViewData;
var userState = "BeginInvoke example";
var invoker = new WorkflowInvoker(HelloMvcDefinition);
Task workflowTask = Task.Factory.FromAsync<IDictionary<string, object>>(
invoker.BeginInvoke(input, WorkflowCompletedCallback, userState),
invoker.EndInvoke);
await workflowTask;
return View();
}
Unfortunately the view does not seem to work. Any ideas on what I am doing wrong?
EDIT After taking advice I have changed the method to this
public class HelloController : AsyncController
{
private static readonly HelloWorkflow HelloMvcDefinition = new HelloWorkflow();
public Task<ViewResult> Index()
{
var input = new Dictionary<string, object>();
input["ViewData"] = ViewData;
const string userState = "BeginInvoke example";
var invoker = new WorkflowInvoker(HelloMvcDefinition);
return Task.Factory.FromAsync<IDictionary<string, object>>(
invoker.BeginInvoke(input, WorkflowCompletedCallback, userState),
invoker.EndInvoke).ContinueWith(t => View());
}
static void WorkflowCompletedCallback(IAsyncResult result)
{
}
}
Which works fine so the problem must be how I am using the async keyword.
Thanks
Upvotes: 0
Views: 874
Reputation: 41
We can use the TAP pattern for invoking windows workflow as follows - (Details are mentioned in my blog post http://tweetycodingxp.blogspot.com/2013/06/invoke-workflow-wf-using-task-based.html)
public async Task<ActionResult> Index(string id)
{
var wfInputArgs = new Dictionary<string, object>
{
...
};
var wfOutputArgs = await Task<IDictionary<string, object>>.Factory.StartNew(
() => WorkflowInvoker.Invoke(new MyWorkflow(), wfInputArgs));
var result = wfOutputArgs["Output1"] as IEnumerable<Class1>;
...
return View(model);
}
Upvotes: 1
Reputation: 457302
Derive from AsyncController
instead of Controller
.
EDIT: You may also be experiencing a known bug where ASP.NET MVC4 will hang if the action returns a completed Task
. You can work around this bug by adding await Task.Yield();
at the top of the action method.
On an unrelated note, this code is more efficient (and shorter, too):
var workflowTask = Task.Factory.FromAsync(invoker.BeginInvoke, invoker.EndInvoke,
input, userState);
Upvotes: 0