Can a task still run if App is hanging? - c#

Can a task still run if an application is in an APPHANG state? On the UI thread, the application is hanging (this is by design as I have forced it for testing how to rectify the issue). I understand that it is not at all good practice to have an application in an apphang state but for testing purposes I'd like to know if other tasks can still run seeing how they are not on the main UI thread.
Or does every task go into a locked state?

Can a task still run if an application is in an APPHANG state?
That depends entirely on the specific task. Some tasks will require the use of the UI thread, based on how they were defined, and some won't.
Perhaps the task is scheduled using a TaskScheduler or SynchronizationContext that intends to marshal the execution of code to the UI thread. Perhaps it will only be completed when some other code running on the UI thread triggers an event. Perhaps it is a continuation of some other task that is in some way dependent on the UI thread. Perhaps it is running code that, through some form of alternate mechanism is dependent on running code in the UI thread. There are literally an infinite number of possible ways, through any number of levels of indirection, for a task to not complete if the UI thread is blocked.
And of course if the UI thread is blocking until the task completes at the same time, then you get a deadlock.
Or does every task go into a locked state?
That's certainly not the case. It's certainly possible to write tasks that will run to completion without regard for what the UI thread is doing.

Related

Is it pointless to use Threads inside Tasks in C#?

I know the differences between a thread and a task., but I cannot understand if creating threads inside tasks is the same as creating only threads.
It depends on how you use the multithreaded capabilities and the asynchronous programming semantics of the language.
Simple facts first. Assume you have an initial, simple, single-threaded, and near empty application (that just reads a line of input with Console.ReadLine for simplicity sake). If you create a new Thread, then you've created it from within another thread, the main thread. Therefore, creating a thread from within a thread is a perfectly valid operation, and the starting point of any multithreaded application.
Now, a Task is not a thread per se, but it gets executed in one when you do Task.Run which is selected from a .NET managed thread pool. As such, if you create a new thread from within a task, you're essentially creating a thread from within a thread (same as above, no harm done). The caveat here is, that you don't have control of the thread or its lifetime, that is, you can't kill it, suspend it, resume it, etc., because you don't have a handle to that thread. If you want some unit of work done, and you don't care which thread does it, just that's it not the current one, then Task.Run is basically the way to go. With that said, you can always start a new thread from within a task, actually, you can even start a task from within a task, and here is some official documentation on unwrapping nested tasks.
Also, you can await inside a task, and create a new thread inside an async method if you want. However, the usability pattern for async and await is that you use them for I/O bound operations, these are operations that require little CPU time but can take long because they need to wait for something, such as network requests, and disk access. For responsive UI implementations, this technique is often used to prevent blocking of the UI by another operation.
As for being pointless or not, it's a use case scenario. I've faced situations where that could have been the solution, but found that redesigning my program logic so that if I need to use a thread from within a task, then what I do is to have two tasks instead of one task plus the inner thread, gave me a cleaner, and more readable code structure, but that it's just personal flair.
As a final note, here are some links to official documentation and another post regarding multithreaded programming in C#:
Async in Depth
Task based asynchronous programming
Chaining Tasks using Continuation Tasks
Start multiple async Tasks and process them as they complete
Should one use Task.Run within another Task
It depends how you use tasks and what your reason is for wanting another thread.
Task.Run
If you use Task.Run, the work will "run on the ThreadPool". It will be done on a different thread than the one you call it from. This is useful in a desktop application where you have a long-running processor-intensive operation that you just need to get off the UI thread.
The difference is that you don't have a handle to the thread, so you can't control that thread in any way (suspend, resume, kill, reuse, etc.). Essentially, you use Task.Run when you don't care which thread the work happens on, as long as it's not the current one.
So if you use Task.Run to start a task, there's nothing stopping you from starting a new thread within, if you know why you're doing it. You could pass the thread handle between tasks if you specifically want to reuse it for a specific purpose.
Async methods
Methods that use async and await are used for operations that use very little processing time, but have I/O operations - operations that require waiting. For example, network requests, read/writing local storage, etc. Using async and await means that the thread is free to do other things while you wait for a response. The benefits depend on the type of application:
Desktop app: The UI thread will be free to respond to user input while you wait for a response. I'm sure you've seen some programs that totally freeze while waiting for a response from something. This is what asynchronous programming helps you avoid.
Web app: The current thread will be freed up to do any other work required. This can include serving other incoming requests. The result is that your application can handle a bigger load than it could if you didn't use async and await.
There is nothing stopping you from starting a thread inside an async method too. You might want to move some processor-intensive work to another thread. But in that case you could use Task.Run too. So it all depends on why you want another thread.
It would be pointless in most cases of everyday programming.
There are situations where you would create threads.

C# Task.Factory.StartNew Longrunning

I would like to find out why the following needs to be blocked in order to get the console to write:
Task.Factory.StartNew(() => Console.WriteLine("KO"), TaskCreationOptions.LongRunning);
and this does not:
new Thread(() => Console.WriteLine("KO")).Start();
According to C# 5.0 in a nutshell, TaskCreationOptions.LongRunning is supposed to make the task NOT use pooled threads (which are background threads), meaning it should be using a foreground thread just like a regular thread, except with a regular thread, one does not need to Console.Readline or Wait() but with a Task, doesn't matter whether it's long running or not, I always have to block the main thread in some way.
So what good is LongRunning or OnComplete() or GetAwaiter() or GetResult() or any other function which is supposed to render a result If I always have to block the main thread myself to actually get the result?
You're relying on undefined behaviour. Don't do that.
You don't need to wait for a task to have it work - it's just the only way to be sure that it actually completed in some way. I assume you're just using a console application with nothing but the code above - by the time the thread actually gets to the Console.WriteLine part, the main thread is dead, and with it all the background threads. new Thread creates a foreground thread by default, which prevents the application as a whole from exiting, despite the fact that the "main" thread was terminated.
The idea behind tasks (and any kind of asynchronous operations, really) is that they allow you to make concurrent requests, and build chains of asynchronous operations (making them behave synchronously, which you usually want). But you still need points of synchronization to actually make a workable application - if your application exits before the tasks are done, too bad :)
You can see this if you just do a Console.ReadLine instead of waiting for the task to finish explicitly - it still runs in the background, independently of the main thread of execution, but now you give it enough time to complete. In most applications, you do asynchronous operations asynchronously to the main thread - for example, a result of a button click might be an asynchronous HTTP request that doesn't block the UI, but if the UI is closed, the request is still terminated.

Why does task.Wait not deadlock on a non-ui thread? Or am I just lucky?

First a small bit of background information. I am in the process of making existing C# library code suitable for execution on WinRT. As a minor part of this code deep down needs to do a little file IO, we first tried to keep things synchronous and used Task.Wait() to stop the main thread until all IO was done.
Sure enough, we quickly found out that leads to a deadlock.
I then found myself changing a lot of code in a prototype to make it "asynchronous". That is, I was inserting async and await keywords, and I was changing the method return types accordingly. This was a lot of work - too much senseless work in fact -, but I got the prototype working this way.
Then I did an experiment, and I ran the original code with the Wait statement on a separate thread:
System.Threading.Tasks.Task.Run(()=> Draw(..., cancellationToken)
No deadlock!
Now I am seriously confused, because I thought that I understood how async programming works. Our code does not (yet) use ConfigureAwait(false) at all. So all await statements should continue in the same context as they got invoked in. Right? I assumed that that means: the same thread. Now if this thread has invoked "Wait", this should also lead to a deadlock. But it does not.
Do any of you have a clear rock-solid explanation?
The answer to this will determine whether I will really go through messing up our code by inserting a lot of conditional async/await keywords, or whether I will keep it clean and just use a thread that does a Wait() here and there. If the continuations get run by an arbitrary non-blocked thread, things should be fine. However, if they get run by the UI thread, we may be in trouble if the continuation is computationally expensive.
I hope that the issue is clear. If not, please let me know.
I have an async/await intro on my blog, where I explain exactly what the context is:
It is SynchronizationContext.Current, unless it is null, in which case it is TaskScheduler.Current. Note: if there is no current TaskScheduler, then TaskScheduler.Current is the same as TaskScheduler.Default, which is the thread pool task scheduler.
In today's code, it usually just comes down to whether or not you have a SynchronizationContext; task schedulers aren't used a whole lot today (but will probably become more common in the future). I have an article on SynchronizationContext that describes how it works and some of the implementations provided by .NET.
WinRT and other UI frameworks (WinForms, WPF, Silverlight) all provide a SynchronizationContext for their main UI thread. This context represents just the single thread, so if you mix blocking and asynchronous code, you can quickly encounter deadlocks. I describe why this happens in more detail in a blog post, but in summary the reason why it deadlocks is because the async method is attempting to re-enter its SynchronizationContext (in this case, resume executing on the UI thread), but the UI thread is blocked waiting for that async method to complete.
The thread pool does not have a SynchronizationContext (or TaskScheduler, normally). So if you are executing on a thread pool thread and block on asynchronous code, it will not deadlock. This is because the context captured is the thread pool context (which is not tied to a particular thread), so the async method can re-enter its context (by just running on a thread pool thread) while another thread pool thread is blocked waiting for it to complete.
The answer to this will determine whether I will really go through messing up our code by inserting a lot of conditional async/await keywords, or whether I will keep it clean and just use a thread that does a Wait() here and there.
If your code is async all the way, it shouldn't look messy at all. I'm not sure what you mean by "conditional"; I would just make it all async. await has a "fast path" implementation that makes it synchronous if the operation has already completed.
Blocking on the asynchronous code using a background thread is possible, but it has some caveats:
You don't have the UI context, so you can't do a lot of UI things.
You still have to "sync up" to the UI thread, and your UI thread should not block (e.g., it should await Task.Run(..), not Task.Run(..).Wait()). This is particularly true for WinRT apps.

.NET async, can a single thread time-slice between tasks?

I'm trying to get a grasp on asynchronous programming in C#/.NET. I read an article (link) on Brown University's website for the cs168 course that defines asynchronous programming as interleaving tasks within the same thread. It says, "Now we can introduce the asynchronous model... In this model, the tasks are interleaved with one another, but in a single thread of control", and shows interleaving very clearly in a figure. But I can't seem to get two tasks to interleave within the same thread in .NET. Is there a way to do that?
I wrote some simple apps to try to test this theory, but I'm not sure if I'm doing it correctly. The main program outputs to the screen every so often, using Thread.Sleep() to simulate work. The asynchronous task does the same. If multiple threads are used, the output is interleaved. But I'm trying to test on a single thread.
I have a WPF app that runs everything on the UI thread, but the task and main program always output sequentially. I create and start the task like this:
var taskFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
var task = taskFactory.StartNew(workDelegate);
I have a console app that starts the task delegate using Task.Run(workDelegate);, but that runs them on different thread pool threads. I'm not sure how to make them both run on the same thread. If I try the same approach I used in WPF I get a runtime InvalidOperationException, "The current SynchronizationContext may not be used as a TaskScheduler".
Multiple tasks won't automatically be interleaved on a single thread. To do that, you have to specify the points in task code where the thread is allowed to cut over to another task. You can do this via a mechanism like await Task.Yield. If you're running on a single thread, the thread will not be able to allow other work to progress unless it explicitly yields.
When you use your TaskScheduler to start every task, the message pump in WPF schedules each task to run on the UI thread, and they will run sequentially.
I have a console app that starts the task delegate using Task.Run(workDelegate);, but that runs them on different thread pool threads. I'm not sure how to make them both run on the same thread.
You would need to install a custom SynchronizationContext into a thread which allowed you to post work to that thread.
You cannot run two concurrent Tasks in the same thread-pool thread. Each thread-pool thread can run one Task at a time. If you want to do two things in one thread, your options what I see now:
1. Combine the two things into one Task
2. Create two tasks and one would depend on the other one. SO in the end they would run sequentially after each other. By default it's not guaranteed that they would run in the same thread though, but you should not rely on that anyway.
It's not clear to me what you want to do. According to the books the UI and the thread of your WPF should do any heavy lifting number crunching work. It should take care of the UI and organize the worker threads/tasks. You would start operations in the background using async.

C# network application threading causes program to block

I am working on a network application with threading. I have an event handler which results in a form showing on the screen. The problem is that the thread that makes this call blocks right after, so the form that shows blocks as well.
I have hacked this problem by making that function change something in the form it's currently in, and then used invoke required to force the new form onto that thread. This is a terrible hack, what is the right way to make the new form.Show() method go through its own thread.
Note that I have tried just making a worker thread that runs only form.show() but the form disappears right after the call.
Thank you,
PM
You don't want UI elements being created in their own threads. The primary thread that launched your application should be the UI thread. Create and show all elements on this thread. All your heavy, long-time or blocking work should be done on their own threads.
You can use BackgroundWorker to execute a single additional task without blocking your UI and get automatic synchronization when you need to make updates to the main (UI) thread such as to update progress bars or show a final result.
If you need multiple threads doing long-running work, use the ThreadPool. You will have to do your own cross-thread synchronization if you need to update UI elements. There are a ton of answers on how to do that already if that's the route you go.
If you have multiple threads that are being blocked while waiting for something to happen, you should use threads yourself. This will keep the ThreadPool from being starved of threads because they are all blocking. (I believe this has been changed in .NET 4 so if you're targeting that version you can probably easily continue using the ThreadPool in this situation.)
Have you tried placing the blocking call in a BackgroundWorker (separate thread)? When that blocking call is done, your background-worker thread completes (which is handled by your main UI thread). Then in that completed handler you can show your form/message or whatever...
If you haven't tried that then give it a shot. Note that i have not tested this since i dont know exactly what you're doing.
Cheers.

Categories

Resources