Reputation: 41
In blazor class I am calling hub async method with cancellation token on button click
tokensource = new CancellationTokenSource();
token = tokensource.Token;
await _hubConnection.SendAsync("MachineOperationOnServer", MachineID, cancellationToken:token).ConfigureAwait(false);
On Button click I am cancelling the CancellationTokenSource
tokensource.Cancel();
In hub class the method is
public async Task MachineOperationOnServer(int machineID)
{
await Task.Factory.StartNew(async () =>
{
int progressPer = 0;
for (int i = 1; i < 20; i++)
{
progressPer = Convert.ToInt32(((decimal)i / 20) * 100);
await Clients.Client(Context.ConnectionId).SendAsync("ProgressOnClient", progressPer);
Thread.Sleep(1000);
}
});
}
Upvotes: 1
Views: 702
Reputation: 2044
There are async methods, which provide a state machine and convenient callback convention within C# code...but what I'm going to suggest is an asynchronous request...where the server receives a request and returns a confirmation before the work for the request completes.
Create a class to hold your Correlation. This will be a reference to the long running task, a request id, and a task completion source that could be used to cancel the task.
When the client calls to start the long running task, the server creates a Correlation instance, assigns it a unique ID (I'd suggest Guid.NewGuid()), starts the task (passing it the id and the cancellation token) and then stores the correlation somewhere it can be found later: I'd recommend a Dictionary<Guid, Correlation>. The server then returns the id. This id is your request id (sometimes also called an opaque identifier if the client isn't supposed to do anything with it but use it blindly for future related calls).
Now your server process will need to remove itself from the dictionary when it is done running, and you'll need to add a new cancel method to the server hub so that the client can request a cancel. If the client requests a cancel, they have to pass the request id, and then the server can look up the correlation and cancel the task by calling cancel on the task completion source. After a cancel you should also remove the correlation from the dictionary.
Its more complicated if you need a return result, but I'll leave that one up to you to figure out. There are a lot of gotchas to this type of coding, and you'll also need to worry about thread safety around access to your dictionary.
Upvotes: 2