简体   繁体   中英

How to get feedback to a page from a running thread in ASP.NET?

So I have this interface that is just one big GO button that syncs a bunch of data from one tool to another. The problem is it takes a really long freaking time and some users are left wondering whats the deal. So I am wondering if there is a way that I can put something in my loop so that every so many entries it sends something back to the page to update them on the progress.

Currently it is just an .aspx page with an aspx.cs behind it. The Go button fires off the whole process and it calls Response.Write a ton of times (as well as writing the same thing to a log file I made) but the Responses don't show until the entire thing is done.

Please advise.

You could design a class which will be stored in the session and which will represent the current state of the operation:

public class OperationState
{
    public object Result { get; set; }
    public int Progress { get; set; }
    public string Error { get; set; }
}

An instance of this class could be created when you start the operation and store it in the user session. Then at each step of the operation you could retrieve it from session and update the progress property. Once the operation terminates you could set the Result property or the Error property in case an exception occurs. In the meantime you could design a PageMethod which will be accessible from client script. This method will simply return the State instance from the session. You will then invoke it periodically and asynchronously from javascript to check the progress and update the DOM to notify the user.

I am assuming you are calling another class to do the work. Lets call this the WorkerClass

You can have the WorkerClass have an event hooked up to it, that the .aspx page hooks up too and will write a message when the event is triggered.

// Overload EventArgs to send messageas back up
public delegate void UpdateMethod(object sender, EventArgs e);

public class WorkerClass
{
    public event UpdateMethod UpdateMethod;
}

WorkerClass worker = new WorkerClass();

worker.UpdateMethod += new UpdateMethod(worker_UpdateMethod);

EDIT based on Comment it is on there page

If you don't want to refactor to another class doing the work (which I suggest). You can post the messages this way.

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);

    this.ProcessMassiveWorkLoad();
}

private void ProcessMassiveWorkLoad()
{
    for(int i = 0; i < 100000; i++)
    {
        // Do some work

        // Write the fact you have work
        Response.Write(string.Format("Done {0} of 100000", i);
    }
}

The simplest way to resolve your issue is to call Response.Flush() after each Response.Write .

This will flush the current response buffer back to the client, enabling them to see the current state of the page.

Even David's method would need this to get the responses out to the user in a timely manner.

The better solution would be along the lines of Darin's solution, which would involve some client side scripting of (say) an update panel, that you refresh with a JavaScript timer to get the latest state, but that may introduce other issues for you (needing JavaScript turned on, rewriting the long running method as something you can fire off asynchronously, etc).

If it's any consolation, I've done both in the past, and would use either again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM