Anyname Donotcare Anyname Donotcare - 1 year ago 74
Ajax Question

How to show an informative real time progress data during long server process

I have a so long process may take 1 hour .

This process consists of many steps run from year to year .My main problem is :

How to provide an informative real time progress to the end user during the process not just a dummy loading bar.

int index = Convert.ToInt32(e.CommandArgument);
bool done = false;
int res = -1;
int fromVal = int.Parse(gv_balance.Rows[index].Cells[0].Text);
int toVal = int.Parse(gv_balance.Rows[index].Cells[1].Text);
int finMonth = 1;
int finYear = 0;
int EndServ = 0;
int calcYear = int.Parse(gv_balance.Rows[index].Cells[2].Text);
int total;
total = ((toVal - fromVal) + 1);
string msg = string.Empty;

int confirm = Balance.GetConfirmState(calcYear);
if (confirm == 0)
{
RadProgressContext progress = RadProgressContext.Current;
progress.Speed = "N/A";

finYear = fromVal;

for (int i = fromVal; i <= toVal; i++)
{
decimal ratio;
//Load New Employees
if (toVal - fromVal > 0)
{
ratio = ((decimal)toVal - i) / (toVal - fromVal) * 100;
}
else
{
ratio = ((decimal)toVal - i) / 1 * 100;
}
progress.PrimaryTotal = total;
progress.PrimaryValue = total;
progress.PrimaryPercent = 100;

progress.SecondaryTotal = 100; // total;
progress.SecondaryValue = ratio;//i ;
progress.SecondaryPercent = ratio; //i;


progress.CurrentOperationText = "Step " + i.ToString();
if (!Response.IsClientConnected)
{
//Cancel button was clicked or the browser was closed, so stop processing
break;
}

progress.TimeEstimated = (toVal - i) * 100;
//Stall the current thread for 0.1 seconds
System.Threading.Thread.Sleep(100);
EndServ = i + 1;
if (i == fromVal)
{
//--->STEP1
//Load intial data
int intial = Balance.PrepareIntialData(calcYear);
//--->STEP2
res = Balance.CalcEndServed(calcYear, EndServ - 1, 6, 30);

}
//--->STEP3
int newEmps = Balance.PrepareNewEmployees(calcYear, i);

for (int j = 0; j < 2; j++)
{
if (j == 0)
{
finMonth = 7;
finYear = i;

}
else
{
finMonth = 1;
finYear = i + 1;
}
//--->STEP4
int promotion1 = Balance.PreparePromotionFirst(finYear, finMonth, calcYear);
//--->STEP5
int promotion2 = Balance.PreparePromotionSecond(finYear, finMonth, calcYear);
//--->STEP6
int appointment1 = Balance.PrepareAppointmentFirst(finYear, finMonth, calcYear);
//--->STEP7
int appointment2 = Balance.PrepareAppointmentSecond(finYear, finMonth, calcYear);

//--->STEP8
int bonus = Balance.PrepareBonus(finMonth, finYear, 0, calcYear);

//--->STEP9
int salary = Balance.PrepareSalary(finYear, finMonth, calcYear);
(((CheckBox)gv_balance.Rows[index].Cells[3].FindControl("chk_redirect")).Checked == true)
{
//--->STEP9
int acco = Balance.PrepareFinanceAccount(finYear, finMonth, calcYear);
}

}


//--->STEP10
res = Balance.CalcEndServed(calcYear, EndServ, 6, 30);
Balance.CalcStudy(calcYear);
UpdateProgressContext();
if (res < 0)
{

success_lb.Visible = false;
error_lb.Visible = true;
error_lb.Text = "ERROR";

}
else
{
done = true;
success_lb.Visible = true;
error_lb.Visible = false;
success_lb.Text = "Success";
}


}
}





I want to show the current step for example :
(Promotion 1 ) in ---> 1-2018
and the percentage of the whole process beside the estimated time .

Answer Source

To report progress of a very long task using signalR you can do something like this (it's only an example to show how it can work):

Server part

We start by mapping SignalR.

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
       // Any connection or hub wire up and configuration should go here
       app.MapSignalR();
   }
}

We create a hub class (don't forget to install the signalr package):

(If you want to report progress to all connected users or a specific group of users take a look here : http://www.asp.net/signalr/overview/guide-to-the-api/working-with-groups)

In the given example it report progress only to the caller of the Start function.

public class MyHub : Hub
{     
    public void Start(string arg)
    {
        Task.Run(() =>
        {
            AVeryLongTask();
        });
    }

    //simulate a long task
    void AVeryLongTask()
    {
        for (int i = 0; i < 10000; i++)
        {
            Thread.Sleep(100);              
            Clients.Caller.ReportProgress("AVeryLongTask", i * 100 / 10000);
        }
    }
}

Client Part

In the html you must add these references :

<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-1.6.4.min.js"></script>
<!--Reference the SignalR library. -->
<script src="/Scripts/jquery.signalR-2.0.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>

and now the Js part to get the progress from the hub :

 $(function() {
   // Declare a proxy to reference the hub.
   var hub = $.connection.myHub;
   // Create a function that the hub can call to report progress.
   hub.client.reportProgress = function(functionName, progress) {
     $('#progression').append('<li><strong>' + progress + '</strong>:&nbsp;&nbsp;' + functionName + '</li>');
   };
   // Start the connection.
   $.connection.hub.start().done(function() {
     $('#startlongprocess').click(function() {
      //start the long process
       hub.server.start("arg");
       alert("started");
     });
   });
 });

The html container for the progress and the start button :

<div class="container">    
   <input type="button" id="startlongprocess" value="Send" />
   <ul id="progression"></ul>
</div>

If you need more explanations don't hesitate to ask.

( My example is based on this one http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr from signalr team )

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download