Jimmy Collins
Jimmy Collins

Reputation: 3304

How to run lengthy tasks from an ASP.NET page?

I've got an ASP.NET page with a simple form. The user fills out the form with some details, uploads a document, and some processing of the file then needs to happens on the server side.

My question is - what's the best approach to handling the server side processing of the files? The processing involves calling an exe. Should I use seperate threads for this?

Ideally I want the user to submit the form without the web page just hanging there while the processing takes place.

I've tried this code but my task never runs on the server:

Action<object> action = (object obj) =>
{
      // Create a .xdu file for this job
       string xduFile = launcher.CreateSingleJobBatchFile(LanguagePair, SourceFileLocation);

      // Launch the job                 
      launcher.ProcessJob(xduFile);
};

Task job = new Task(action, "test");
job.Start();

Any suggestions are appreciated.

Upvotes: 4

Views: 1006

Answers (3)

Enrico Campidoglio
Enrico Campidoglio

Reputation: 59983

You could invoke the processing functionality asynchronously in a classic fire and forget fashion:

In .NET 4.0 you should do this using the new Task Parallel Library:

Task.Factory.StartNew(() =>
{
    // Do work
});

If you need to pass an argument to the action delegate you could do it like this:

Action<object> task = args =>
{
    // Do work with args
};    
Task.Factory.StartNew(task, "SomeArgument");

In .NET 3.5 and earlier you would instead do it this way:

ThreadPool.QueueUserWorkItem(args =>
{
   // Do work
});

Related resources:

Upvotes: 6

asawyer
asawyer

Reputation: 17808

I have a site that does some potentially long running stuff that needs to be responsive and update a timer for the user.

My solution was to build a state machine into the page with a hidden value and some session values.

I have these on my aspx side:

<asp:Timer ID="Timer1" runat="server" Interval="1600" />
<asp:HiddenField runat="server" ID="hdnASynchStatus" Value="" />

And my code looks something like:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    PostbackStateEngineStep()
    UpdateElapsedTime()
End Sub

Private Sub PostbackStateEngineStep()
    If hdnASynchStatus.Value = "" And Not CBool(Session("WaitingForCallback")) Then

        Dim i As IAsyncResult = {...run something that spawns in it's own thread, and calls ProcessCallBack when it's done...}

        Session.Add("WaitingForCallback", True)
        Session.Add("InvokeTime", DateTime.Now)
        hdnASynchStatus.Value = "WaitingForCallback"
    ElseIf CBool(Session("WaitingForCallback")) Then
        If Not CBool(Session("ProcessComplete")) Then
            hdnASynchStatus.Value = "WaitingForCallback"
        Else
            'ALL DONE HERE
            'redirect to the next page now
            response.redirect(...)
        End If
    Else
        hdnASynchStatus.Value = "DoProcessing"
    End If
End Sub
Public Sub ProcessCallBack(ByVal ar As IAsyncResult)
    Session.Add("ProcessComplete", True)
End Sub
Private Sub UpdateElapsedTime()
    'update a label with the elapsed time
End Sub

Upvotes: 1

mellamokb
mellamokb

Reputation: 56779

Use:

ThreadPool.QueueUserWorkItem(o => MyFunc(arg0, arg1, ...));

Where MyFunc() does the server-side processing in the background after the user submits the page;

Upvotes: 2

Related Questions