Support Co-operative Cancellation of all methods that can.

Advertisement

A9G-Data-Droid
A9G-Data-Droid avatar
Joined:
Posts:
5
Location:
Space

Support Co-operative Cancellation of all methods that can.

The current suggested method to cancel an operation is setting a bool on an FileTransferProgressEventArgs.
https://winscp.net/eng/docs/library_filetransferprogresseventargs#cancel

This is an anti-pattern in C#. I'm not even sure how my event handling delegate would know if cancellation is requested. An event handling delegate is usually a static method that has no knowledge of its own. Plus the event comes in on a different thread from where the transfer occurred.

The cancellation pattern in C# is generally to pass a CancellationToken to each operation that supports cancellation as a final, optional, argument. This way you can cancel a single download but not effect an upload elsewhere.

If the transfer method had this token it would simply set the:
FileTransferProgressEventArgs.Cancel = CancellationToken.IsCancellationRequested
Whenever a new FileTransferProgressEventArgs is created. This way, it cancels itself co-operatively and the cancelled state is then visible in the next event. The event tells you information, not the other way around.

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
41,517
Location:
Prague, Czechia

Re: Support Co-operative Cancellation of all methods that can.

This way you can cancel a single download but not effect an upload elsewhere.
I do not follow. The WinSCP .NET assembly API is synchronous. You cannot be downloading and uploading at the same time.

Reply with quote

A9G-Data-Droid
A9G-Data-Droid avatar
Joined:
Posts:
5
Location:
Space

Re: Support Co-operative Cancellation of all methods that can.

While synchronous, it does support cancellation, and report status on a separate thread.

My library spins up both multiple concurrent operations per session and multiple sessions. I'm new to this library so I'm not sure if that is an expected use case but it works. I am currently passing a cancel token where the session is created, because the event handler is session level. This allows me to cancel all operations in a session. Further granularity would require a lot more code.

That is all beside the point. The point is that any operation that can be cancelled should accept a cancellation token.

I'm not sure how you are currently interrupting the transfer but there is a similar C++ feature:
http://www.modernescpp.com/index.php/a-new-thread-with-c-20-std-jthread/

I apologize if this is way off base. I'm not well versed in C++.

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
41,517
Location:
Prague, Czechia

Re: Support Co-operative Cancellation of all methods that can.

If I understand it correctly, the point of the token is that with asynchronous API, you might be having multiple outstanding asynchronous operations going on over the same object. So you need the token to be able to distinguish the operation to cancel.

With with WinSCP, you always have only a single outstanding operation. So there's no need for a token. Or in other words the Session instance is the token.

Or do you have any other example of synchronous API with a cancellation token?

Reply with quote

A9G-Data-Droid
A9G-Data-Droid avatar
Joined:
Posts:
5
Location:
Space

Re: Support Co-operative Cancellation of all methods that can.

I'm not sure I understand. I have sent many operations to a single Session instance. Cancellation Token is for Operations, not Objects. One cancellation token should refer to a “cancellable operation”. Once the IsCancellationRequested property in a cancellation token is set to true, it can’t be set to false again and you can't reuse the same cancellation token again after its cancelled. So if you were doing multiple things with a session that had a cancellation token attached to its FileTransferProgress event then all events would be cancelled, not just a single operation.

martin wrote:

Or do you have any other example of synchronous API with a cancellation token?
The Microsoft documentation states "Starting with .NET Framework 4, .NET uses a unified model for cooperative cancellation of asynchronous or long-running synchronous operations." in this article: https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads

Stephen Cleary shows the most simple example of using Cancellation Tokens in synchronous methods here: https://blog.stephencleary.com/2022/03/cancellation-4-polling.html

Looking at C++ examples, the code looks very similar. The C# cancellation token could be linked to a stop token where stoken.stop_requested() can be checked to interrupt an operation the same way we check for IsCancellationRequested in C#. These patterns were modeled after C# so I'm sure there are people using them this way. Seen here: https://www.nextptr.com/tutorial/ta1588653702/stdjthread-and-cooperative-cancellation-with-stop-token

Reply with quote

Advertisement

martin
Site Admin
martin avatar

Re: Support Co-operative Cancellation of all methods that can.

I'm not sure we understand each other. What do you mean by "doing multiple things with a session"? You cannot be doing multiple things with a WinSCP Session.

Reply with quote

Advertisement

You can post new topics in this forum