How to cancel Task without CancellationToken.IsCancellationRequested? - task

I am developing a WPF application with C# 4.0 where some user-specific code will
be compiled at runtime and then executed inside an AppDomain. The process might take 10 ms or 5 minutes. The AppDomain will be created by Task.Factory.StartNew(). Works fine.
Now I want to be able to cancel/interrupt the execution. I can press a
Stop button while the codes is executing but how can I cancel the Task? I know:
there is the CancellationToken.IsCancellationRequested property but I cannot
loop through something. This is why I cannot check the value while executing
the (atomic) code. And unloading the AppDomain does not stop the Task.
FYI: I took the Task class because it easy to use. If Thread would be useful: No problem.
Can someone help me? A short code snippet would be nice :).
Thank you.

Aborting a thread or a task is a code smell of a badly designed solution.
If that is your decision, you should consider that every line of code could be the last one to be executed and consider releasing any unmanaged resource, lock, etc that could leave the system in an inconsistent state. In theory we should always be this careful, but in practice this doesn't hold.
If you try with a Thread and the inviting .Abort() method, you should consider that ThreadAbortException is a special exception in terms of try-catch and finally blocks. Additionally, you can't even be sure that the thread is going to be aborted.
In regards of using a Task, AFAIK (I'm not an expert in TPL) I'm afraid you cannot do what you want. You should somehow re-design your logic to consider the cancellation token and cleanly stop your computation.

Related

Why is it the programmer’s responsibility to call things on the main thread?

Why is it the responsibility of the programmer to call UI related methods on the main thread with:
DispatchQueue.main.async {}
Theoretically, couldn’t this be left up to the compiler or some other agent to determine?
The actual answer is developer inertia and grandfathering.
The Cocoa UI API is huge—nay, gigantic. It has also been in continuous development since the 1990's.
Back when I was a youth and there were no multi-core, 64-bit, anything, 99.999% of all applications ran on the main thread. Period. (The original Mac OS, pre-OS X, didn't even have threads.)
Later, a few specialized tasks could be run on background threads, but largely apps still ran on the main thread.
Fast forward to today where it's trivial to dispatch thousands of tasks for background execution and CPUs can run 30 or more current threads, it's easy to say "hey, why doesn't the compiler/API/OS handle this main-thread thing for me?" But what's nigh on impossible is re-engineering four decades of Cocoa code and apps to make that work.
There are—I'm going to say—hundreds of millions of lines of code that all assume UI calls are executing concurrently on the main thread. As others have pointed out, there is no cleaver switch or pre-processor that's going to undo all of those assumptions, fix all of those potential deadlocks, etc.
(Heck, if the compiler could figure this kind of stuff out we wouldn't even have to write multi-threaded code; you'd just let the compiler slice up your code so it runs concurrently.)
Finally, such a change just isn't worth the effort. I do Cocoa development full time and the number of times I have to deal with the "update control from a background thread problem" occurs, at most, once a week or so. There's no development cost-benefit analysis that's going to dedicate a million man-hours to solving a problem that already has a straight forward solution.
Now if you were developing a new, modern, UI API from scratch, you'd simply make the entire UI framework thread safe and whole question goes away. And maybe Apple has a brand new, redesigned-from-the-ground-up, UI framework in a lab somewhere that does that. But that's the only way I see something like this happening.
You would be substituting one kind of frustration for another.
Suppose that all UI-related methods that require invocation on the main thread did so by:
using DispatchQueue.main.async: You would be hiding asynchronous behaviour, with no obvious way to "follow up" on the result. Code like this would now fail:
label.text = "new value"
assert(label.text == "new value")
You would have thought that the property text just harmlessly assigned some value. In fact, it enqueued a work item to asynchronously execute on the main thread. In doing so, you've broken the expectation that your system has reached its desired state by the time you've completed that line.
using DispatchQueue.main.sync: You would be hiding a potential for deadlock. Synchronous code on the main queue can be very dangerous, because it's easy to unintentionally block (on the main thread) yourself waiting for such work, causing deadlock.
I think one way this could have been achieved is by having a hidden thread dedicated to UI. All UI-related APIs would switch to that thread to do their work. Though I don't know how expensive that would be (each switch to that thread is probably no faster than waiting on a lock), and I could imagine there's lots of "fun" ways that'll get you to write deadlocking code.
Only on rare instances would the UI call anything in the main thread, except for user login timeouts for security. Most UI related methods for any particular window are called within the thread that was started when the window was initialized.
I would rather manage my UI calls instead of the compiler because as a developer, I want control and do not want to rely on third party 'black boxes'.
check https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
and UPDATE UI FROM MAIN THREAD ONLY!!!

grpc iOS stream, send only when GRXWriter.state is started?

I'm using grpc in iOS with bidirectional streams.
For the stream that I write to, I subclassed GRXWriter and I'm writing to it from a background thread.
I want to be as quick as possible. However, I see that GRXWriter's status switches between started and paused, and I sometimes get an exception when I write to it during the paused state. I found that before writing, I have to wait for GRXWriter.state to become started. Is this really a requirement? Is GRXWriter only allowed to write when its state is started? It switches very often between started and paused, and this feels like it may be slowing me down.
Another issue with this state check is that my code looks ugly. Is there any other way that I can use bidirectional streams in a nicer way? In C# grpc, I just get a stream that I write freely to.
Edit: I guess the reason I'm asking is this: in my thread that writes to GRXWriter, I have a while loop that keeps checking whether state is started and does nothing if it is not. Is there a better way to do this rather than polling the state?
The GRXWriter pauses because the gRPC Core only accepts one write operation pending at a time. The next one has to wait until the first one completes. So the GRPCCall instance will block the writer until the previous write is completed, by modifying its state!
In terms of the exception, I am not sure why you are getting the problem. GRXWriter is more like an abstract class and it seems you did your own implementation by inheriting from it. If you really want to do so, it might be helpful to refer to GRXBufferedPipe, which is an internal implementation. In particular, if you want to avoid waiting in a loop for writing, writing again in the setter of GRXWriter's state should be a good option.

C# 5 .NET MVC long async task, progress report and cancel globally

I use ASP.Net MVC 5 and I have a long running action which have to poll webservices, process data and store them in database.
For that I want to use TPL library to start the task async.
But I wonder how to do 3 things :
I want to report progress of this task. For this I think about SignalR
I want to be able to left the page where I start this task from and be able to report the progression across the website (from a panel on the left but this is ok)
And I want to be able to cancel this task globally (from my panel on the left)
I know quite a few about all of technologies involved. But I'm not sure about the best way to achieve this.
Is someone can help me about the best solution ?
The fact that you want to run long running work while the user can navigate away from the page that initiates the work means that you need to run this work "in the background". It cannot be performed as part of a regular HTTP request because the user might cancel his request at any time by navigating away or closing the browser. In fact this seems to be a key scenario for you.
Background work in ASP.NET is dangerous. You can certainly pull it off but it is not easy to get right. Also, worker processes can exit for many reasons (app pool recycle, deployment, machine reboot, machine failure, Stack Overflow or OOM exception on an unrelated thread). So make sure your long-running work tolerates being aborted mid-way. You can reduce the likelyhood that this happens but never exclude the possibility.
You can make your code safe in the face of arbitrary termination by wrapping all work in a transaction. This of course only works if you don't cause non-transacted side-effects like web-service calls that change state. It is not possible to give a general answer here because achieving safety in the presence of arbitrary termination depends highly on the concrete work to be done.
Here's a possible architecture that I have used in the past:
When a job comes in you write all necessary input data to a database table and report success to the client.
You need a way to start a worker to work on that job. You could start a task immediately for that. You also need a periodic check that looks for unstarted work in case the app exits after having added the work item but before starting a task for it. Have the Windows task scheduler call a secret URL in your app once per minute that does this.
When you start working on a job you mark that job as running so that it is not accidentally picked up a second time. Work on that job, write the results and mark it as done. All in a single transaction. When your process happens to exit mid-way the database will reset all data involved.
Write job progress to a separate table row on a separate connection and separate transaction. The browser can poll the server for progress information. You could also use SignalR but I don't have experience with that and I expect it would be hard to get it to resume progress reporting in the presence of arbitrary termination.
Cancellation would be done by setting a cancel flag in the progress information row. The app needs to poll that flag.
Maybe you can make use of message queueing for job processing but I'm always wary to use it. To process a message in a transacted way you need MSDTC which is unsupported with many high-availability solutions for SQL Server.
You might think that this architecture is not very sophisticated. It makes use of polling for lots of things. Polling is a primitive technique but it works quite well. It is reliable and well-understood. It has a simple concurrency model.
If you can assume that your application never exits at inopportune times the architecture would be much simpler. But this cannot be assumed. You cannot assume that there will be no deployments during work hours and that there will be no bugs leading to crashes.
Even if using http worker is a bad thing to run long task I have made a small example of how to manage it with SignalR :
Inside this example you can :
Start a task
See task progression
Cancel task
It's based on :
twitter bootstrap
knockoutjs
signalR
C# 5.0 async/await with CancelToken and IProgress
You can find the source of this example here :
https://github.com/dragouf/SignalR.Progress

If terminating a hung thread is a good idea, how do I do it safely?

My Delphi program relies heavily on Outlook automation. Outlook versions prior to 2007-SP2 tend to get stuck in memory due to badly written addins and badly written Outlook code.
If Outlook is stuck, calling CreateOleObject('Outlook.Application') or GetActiveObject ... doesn't return and keeps my application hanging till Outlook.exe is closed in the task manager.
I've thought of a solution, but I'm unsure whether it's good practice or not.
I'd start Outlook with CreateOleObject in a separate thread, wait 10 seconds in my main thread and if Outlook hangs (CreateOleObject doesn't return), offer the user to kill the Outlook.exe process from my program.
But since I don't want to force the user to kill the Outlook.exe process, as an alternative I also need a way to kill the new thread in my program which keeps hanging now.
Is this good practice?
How can I terminate a hanging thread in Delphi without leaking memory?
Windows has a TerminateThread function, but as you can see from the remarks, it's not generally a good idea to use it. A safer approach would be to have a secondary application that interacts with Outlook, and you could then kill that without affecting your own application's stability. TerminateProcess would work, but if you wanted to be a little friendlier to the system Dr. Dobbs has an article on a possibly safer approach using ExitProcess.
If the hang is consistent and always either happens or doesn't happen, you can just call CreateOleObject in the app and exit, then call it again from your own. If it's inconsistent the secondary application could be a more complete wrapper, and all the interactions would go through it.
And additionally, you can use thread's Context's eip register.
You can find a sample at;
http://www.tugrulhelvaci.com/?p=568

How do you cleanly abort a Delphi program?

I've got a program that's having some trouble during shutdown, raising exceptions that I can't trace back to their source. It appears to be timing-related and non-deterministic. This is occurring after all shared resources have been released, and since it's shutdown, memory leaks are not an issue, so that makes me wonder if there's any way to just tell the program to terminate immediately and silently after releasing the shared resources, instead of continuing with the shutdown sequence and giving an exception message box.
Does anyone know how to do that?
After looking at the Delphi Run Time Library source code, and at the Microsoft documentation; I can corroborate Mason and Paul-Jan comments.
The hierarchy of shutdown is as follows
Application.Terminate()
performs some unidentified housekeeping of application
calls Halt()
Halt()
calls ExitProc if set
alerts the user in case of runtime error
get rid of PackageLoad call contexts that might be pending
finalize all units
clear all exception handlers
call ExitprocessProc if set
and finally, call ExitProcess() from 'kernel32.dll'
ExitProcess()
unloads all DLLs
uses TerminateProcess() to kill the process
ExitProcess(0) ?
Halt(0) used to be the good old fashioned way of telling the program to end with immediate effect. There's probably a more Delphi-friendly way of doing that now, but I'm 95% sure halt(0) still works. :-)
In case HeartWare's suggestion of using ExitProcess() fails, it might be you are using some DLL's that do not respond well to the DLL_PROCESS_DETACH. In that case, try using a TerminateProcess( getCurrentProcess, 0 );
Once you resort to such measures, one might wonder if the "cleanly" part of the topic title still holds up to scrutiny.
The last time I had to hunt a problem like this was the shutdown was a causing an event (resize? It's been a while.) to fire on the dying window causing an attempt to redraw something that needed stuff that had already been disposed of.

Resources