I have a Hub class, which has a long running method, I need to display a progress bar while it's working.
I read this article and I think it is possible to use IProgress interface in async methods to send long running operation status.
I write a method like this:
public async Task<string> GetServerTime(IProgress<int> prog)
{
await Task.Run(() => {
for (int i = 0; i < 10; i++)
{
prog.Report(i * 10);
System.Threading.Thread.Sleep(200);
}
});
return DateTime.Now.ToString();
}
And I try to invoke the method like this:
var appHub = $.connection.appHub;
$.connection.hub.start();
appHub.server.getServerTime()
.done(function (time) {
alert(time);
});
But I don't know how can I get the progress reports.
You can use progress
, as such:
var appHub = $.connection.appHub;
$.connection.hub.start().done(function() {
appHub.server.getServerTime()
.progress(function (update) { alert(update); })
.done(function (time) { alert(time); });
});
On a side note, there's no point in using Task.Run
over CPU-bound code on the server side. Your server-side code could just as easily be:
public string GetServerTime(IProgress<int> prog)
{
for (int i = 0; i < 10; i++)
{
prog.Report(i * 10);
System.Threading.Thread.Sleep(200);
}
return DateTime.Now.ToString();
}
Your server-side methods should only be async
if they have true asynchronous work to do (usually I/O-bound operations). As a general rule, avoid Task.Run
on the server side.
In your javascript add the following client method
var appHub = $.connection.appHub;
$.connection.hub.start();
appHub.client.progress = function(progresspct) {
// logic for whatever you want to do.
};
appHub.server.getServerTime()
.done(function (time) {
alert(time);
});
Modify your server side code to this -
public async Task<string> GetServerTime(IProgress<int> prog)
{
await Task.Run(() => {
for (int i = 0; i < 10; i++)
{
prog.Report(i * 10);
// Call to your client side method.
Clients.Client(Context.ConnectionId).progress(i);
System.Threading.Thread.Sleep(200);
}
});
return DateTime.Now.ToString();
}