views:

473

answers:

4

Here is the situation. I need to hit ~50 servers and grab some data from a file. I then want to display a few rows for each in an ASP.NET GridView control.

I tried doing this with Threads/ThreadPool and successfully gather all the data in session.

What I'd like to do, and what I am having a hard time figuring out, is update the grid for the user after each server is done loading.

If I put the databinding code in the thread, it will only display whatever has loaded by the time the response is sent back to the client. If I take it out of the thread, I'd have to wait until all threads were done to send the response, and that doesn't do what I want.

Anyone have any ideas? I seeing some stuff about Asynchronous Client Callbacks, but I'm not sure if that's what I need to be using. I have no idea how to manipulate a GridView from Javascript.

Thanks for any help you can provide.

A: 

I so seldom use ASP.net controls, so I have a hard time answering this. I will say that I would use Ajax to let the client know when to reload the Gridview after each server's data has been finished being retrieved.

I did read a little about something called active widgets, which would replace your gridview.

Here is how I would handle this: On initial construction, provide an eventing mechanism that is fired on every individual server's load task complete, and would store the results to the session. On the client side, keep having an update object update as long as not all server requests are complete. A great data format for this would be JSON.

Anyway, I hope this has helped.

fauxtrot
A: 

You could use just put the gridview into an UpdatePanel and handle your client side callbacks from there, which is probably the simplest implementation for the gridview. Basically you just wrap the gridview with an update panel and anything inside will work using ajax. It is up to you to write efficient code to query your data but the ui should be easier.

You could do it all manually with Javascript and JSON and a client webservice but I would try the update panel first.

JustEngland
+2  A: 

There's no way for the server side ASP.NET code to poke the web browser and to tell it that there's new data available. So you'll have to use to JavaScript to poll the server for new data. There are various ways of doing this. One example would be to use Page Methods on the server side that could tell the client whether there's more data available and when all the data has been loaded.

[WebMethod]
public static bool IsNewDataAvailable(int currentClientRows)
{
    return dataCollectedSoFar.Count > currentClientRows;
}

[WebMethod]
public static bool IsFinished()
{
    // return true if all the threads in the thread pool are finished
}

You need to call the IsNewDataAvailable method at regular intervals. A simple JavaScript timer should do the trick.

When there is new data available, you'll need to re-render the GridView. Again, there's more than one way to do this, but a nice and simple way would be to put the GridView inside an UpdatePanel along side a Button with a style="display: none;" attribute to keep it hidden. Then if there is new data available, simply call the JavaScript click method on the button to update the contents of the update panel.

<script>
var timerId = setInterval("checkForData()", 5000);

function checkForData() {

    // If all threads have finished, stop polling
    if (PageMethods.IsFinished()) {
        clearInterval(timerId);
    }

    var currentRowCount = 0;

    // Find out how many rows you currently have, if 
    // you have jQuery you could do something like this
    currentRowCount = $("#<%= myGridView.ClientID %> tr").length;

    if (PageMethods.IsNewDataAvailable(currentRowCount)) {

        // Here we trigger the hidden button's click method, again
        // using a bit of jQuery to show how it might be done
        $("#<%= myHiddenButton.ClientID %>").click();
    }
}
</script>

. . .

<asp:UpdatePanel ID="myUpdatePanel" runat="server">
    <ContentTemplate>
        <asp:GridView ID="myGridView" runat="server">
            . . .
        </asp:GridView>
        <asp:Button ID="myHiddenButton" runat="server" style="display: none;" OnClientClick="myHiddenButton_Click" />
    </ContentTemplate>
</asp:UpdatePanel>

Finally, to populate the GridView on the server side, you can continue to use a ThreadPool and just render all the data you have each time. For example:

protected void myHiddenButton_Click(object sender, EventArgs e)
{
    myGridView.DataSource = dataCollectedSoFar;
    myGridView.DataBind();
}
d4nt
I like this. All it needs is a way to indicate that all of the data had finished loading so that the browser can stop querying the Page Method.
Daniel Schilling
@Daniel, I've ammended the answer to stop the polling once all the data is loaded
d4nt
A: 

protected void load_Click(object sender, EventArgs e) { sqc.ConnectionString = dbc.sqlconn(); sqc.Open(); OleDbCommand cmd = new OleDbCommand("SELECT cus_serial,cus_name,cus_mobile,no_person,unit_cost,total_cost from booking", sqc); //OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);

    sdr = cmd.ExecuteReader();
    DataTable dt = new DataTable("A");
    dt.Load(sdr);
    GridView1.DataSource = dt;
    GridView1.DataBind();
    sdr.Close();
    sqc.Close();
}
Tonmoy