Cancel python function from dotnet (Python.NET) - c#

I am using Python.NET to call the EasyOCR Python library. Depending on the context, the detection can be slow (from 30s to a couple of minutes) and some actions performed by my user could result in the cancellation of the task. As far as I can tell, the cancellation token will cancel the task only at the next C# instruction so I am stuck while the python code is running.
I have seen that there is some similar mechanism on Python side using asyncio but I was wondering if there was any way to avoid the complexity of having extra python logic by being able to somehow "kill" the python process. Or maybe some easy way to somehow share the token.

A feature very similar to what you are asking has been added to Python.NET recently (you might need to use 3.0 previews though, it probably did not make it into 2.5).
This is the test code, that was added for the feature. I think that is the best reference you will be able to get: https://github.com/pythonnet/pythonnet/pull/1337/files#diff-e846713ba20ecf06af2cc88cc1e92bae49d519998b093d2fb0f7fd6644b10092
Pay attention to the SetUp method too. It shows how to correctly set up multithreading.

There is no good way to abort a non-cooperating thread/task. There is Thread.Abort, but using it is a bad idea. Your options are more or less
Figure out a way to forward the cancellation request to the python code.
Stop waiting for the result when cancelling the task, but let the task continue to run in the background.
Run the task in a separate process, and kill the process on cancel.
Do not allow the task to be cancelled.

Related

Monitoring Edge.js Tasks from C#

My goal is to be able to cancel a long running Node.js task that has been called from C# using Edge.js.
When using tasks normally, you can specify a cancellation token, give your task some time to execute, then cancel it if it is going beyond your time limit.
I can't figure out how to define/call the Edge.Func Node function/task and pass in a cancellation token to be able to kill the process if it goes too long. Maybe I'm thinking about this from the wrong angle...
Any insight would be most helpful, thanks!

Is it good practice to always wait on a task to complete?

Sorry if it is a dumb question. I'm confused about the wait() and its variants in regards to the task parallel library.
Every single example I've seen waits on tasks to complete - is this considered good practice?
My scenario is this, that I'm developing a windows service that will run continuously. I would like to engage a number of tasks, but I don't care if they will run to completion - I will set a cancellation-token with an expiration, that will throw an error if something goes awry. So I don't see the need for a wait-to-complete, but every darn example uses it...
It really depends on what your situations needs. If for instance, you want to launch a sub process to do a procedure, say for instance, fire off an email in parallel you can do without waiting.
However, if you will need to act upon what ever result or structure which is affected by some behavior you will need to wait.
If your tasks are self contained and do not interact and/or depend on each other, then I do not see why you would need to wait.
You only need to wait on a task if the code that is waiting requires the output of the task before it can proceed. If you don't need that output, don't wait.

Cancel an asynchronous call (IAsyncResult)

I am programming in .net WPF.
I have a (third party) API which implements the Begin/End asynchronous call pattern. The BeginWork() function returns an IAsyncResult.
However, there is no apparent method to cancel/abort the call, once done.
Is there a way to have such a job stopped? If this requires the library author to provide explicitly for a cancel method, what is a way to kill this job, even ungracefully? I really need to be able to stop it somehow, as a single job may take hours to complete!
Thanks!
If the implementation does not include specific code allowing for cancellation, then it is quite likely that you can't cancel it. Not everything can be logically cancelled cleanly, especially if it involves external resources. But also if the code to cancel it simply hasn't been written.
.you could try randomly killing threads, but this will doom your process - basically this would be the same as deciding to kill the entire process half way through. It will stop the work, but it could leave things in a complete mess if it isn't transactional.
If I was you I would (one of):
ask the 3rd party for a supported cancellation API
don't start it unless you are sure

How do I cancel a schedule for a task?

I need to create a scheduled task. For that I'm trying to learn how to do that, and am currently thinking of using TaskSchedulerClass from TaskScheduler Class Library. I got a code examples here (and there's another one I might try here). But - I don't want to actually run it without making sure I know how to cancel it when needed.
So my question is: How do I cancel such a task-registration in code?
(Just "Try it!" won't suffice in this case. Because the point is I don't want to get stuck with something I can't stop.)
What about TryDequeue Method?
It's attempts to dequeue a Task that was previously queued to this scheduler.
You need to use the same Task you sent to QueueTask function.
If you don't have the instance of this Task you can try and retrieve it using GetScheduledTasks, but it stated it in use For debugger support only

How to Purge a ThreadPool? [Microsoft System.Threading.ThreadPool]

Is it possible to purge a ThreadPool?
Remove items from the ThreadPool?
Anything like that?
ThreadPool.QueueUserWorkItem(GetDataThread);
RegisteredWaitHandle Handle = ThreadPool.RegisterWaitForSingleObject(CompletedEvent, WaitProc, null, 10000, true);
Any thoughts?
I recommend using the Task class (added in .NET 4.0) if you need this kind of behaviour. It supports cancellation, and you can have any number of tasks listening to the same cancellation token, which enables you to cancel them all with a single method call.
Updated (non-4.0 solution):
You really only have two choices. One: implement your own event demultiplexer (this is far more complex than it appears, due to the 64-handle wait limitation); I can't recommend this - I had to do it once (in unmanaged code), and it was hideous.
That leaves the second choice: Have a signal to cancel the tasks. Naturally, RegisteredWaitHandle.Unregister can cancel the RWFSO part. The QUWI is more complex, but can be done by making the action aware of a "token" value. When the action executes, it first checks the token value against its stored token value; if they are different, then it shouldn't do anything.
One major thing to consider is race conditions. Just keep in mind that there is a race condition between cancelling an action and the ThreadPool executing it, so it is possible to see actions running after cancellation.
I have a blog post on this concept, which I call "asynchronous callback contexts". The CallbackContext type mentioned in the blog post is available in the Nito.Async library.
There's no interface for removing a queued item. However, nothing stops you from "poisoning" the delegate so that it returns immediately.
edit
Based on what Paul said, I'm thinking you might also want to consider a pipelined architecture, where you have a fixed number of threads reading from a blocking queue (like .NET 4.0's BlockingCollection on a ConcurrentQueue). This way, if you want to cancel items, you can just access the queue yourself.
Having said that, Stephen's advice about Task is likely better, in that it gives you all the control you would realistically want, without all the hard work that rolling your own pipelines involves. I mention this only for completion.
The ThreadPool exists to help you manage your threads. You should not have to worry about purging it at all since it will make the best performance decisions on your behalf.
If you think you need tighter control over your threads then you could consider creating your own thread management class (similar to ThreadPool) but it would take a lot of work to match and exceed the functionality that ThreadPool has built in.
Take a look here at some of the ThreadPool optimizations and the ideas behind it.
For my second point, I found an article on Code Project that implements a "Cancelable Threadpool", probably for some of your own similar reasons. It would be a good place to start looking if you're going to write your own.

Categories