Task lifetime Child vs parent - c#

I'm familiar with Task and Threads and I already know this.
Here is my code:
static void Main(string[] args)
{
var t = Task.Factory.StartNew(() => {
Thread.Sleep(3000);
Console.WriteLine("Child");
}, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
Task.WaitAll(t);
Console.WriteLine("Parent");
}
Does Console.WriteLine("Child"); get called regardelss the call of Task.WaitAll(t); In other words: Is there a way to execute ALL started subtasks without waiting them (and not killed as soon as the parent finishes execution)?

A C# program will terminate as soon as there are no foreground threads running. Task.Factory.StartNew uses the thread pool thread to do its work, and thread pool threads are all background threads, not foreground threads, and as such don't prevent the entire program from terminating.
If you want to ensure that the entire program doesn't terminate you need to make sure you have at least one foreground thread running, this means either having the additional work you do in the Task you create do its work in a foreground thread, rather than a background thread (which is appropriate, if you want that work to prevent the application from terminating), or it will mean waiting in your one existing foreground thread for the others to finish.

Related

My thread disappears from thread list after some time

I have multi thread program with C# language.
When load main form, 4 thread start that all of them work with while(true)
Every thread run, active and exist in thread list but after 30 ms, one of thread (without any error) disappear from thread list and doesn't work
even breakpoint not work.
I want read data from TCP and process 3 steps then save to database
Task1: have while(true) and read data from tcp and add to blockingcollection bk1
Task 2: in while(true), take data from bk1 and process data then add data to BlockingCollection bk2
Task3 in while(true) take data from bk2 and process then bk3
Task 4 in while (true) take data from bk3 then insert database
I define task:
Task.Factory.StartNew(() => myfunction, CancellationToken.None,
TaskCreationOptions.PreferFairness, TaskScheduler.Default);
When click button1 all of tasks start and work correctly after some time task3 change status to RanToCompletion and does not work I didn't use async and await in code because task works parallel and don't need wait for other task.
Even TaskCreationOptions set to LongRunning
My function have while(true) and work producer-consumer method.
Please help me about problem.
Thanks for attention.
Your code never awaits that task to end. Use await and Task.Run instead:
await Task.Run(()=>myFunction());
or
await Task.Run(myFunction);
Tasks aren't threads. They're a job that gets executed by a threadpoool thread. Creating a thread is an expensive operation. To avoid the cost of creating and destroying threads, .NET keeps a pool of worker threads. Jobs, in the form of Action or Func delegates, get posted to that ThreadPool and executed by one of the worker threads.
Task.Run or Task.Factor.StartNew post a job to the threadpool for execution and return a Task, essentially a "promise" object. This means the calling thread isn't blocked waiting for the task to complete and can do other work. await makes it easy to await for that task to complete and get back to the calling thread. Once the task completes, execution can resume with the code after await.
In a desktop application that means the UI thread doesn't get blocked waiting for a task to complete and can keep processing Windows messages, button clicks, refresh its windows etc. When the task completes, execution will resume on the UI thread with the code that comes after await.
async void btn1_Click(object sender,EventArgs args)
{
var customerName=txtCustomer.Text;
var orders=await Task.Run(()=>LoadOrdersFromDbAsync(customerName));
grdOrders.DataSource=orders;
}

Background thread executed event after foreground thread exited?

I was going through Microsoft docs for ThreadPool and they explained that ThreadPool threads are background threads which do not keep the application running if all foreground threads have terminated.
Here is the code snippet:
public static void Main()
{
ThreadPool.QueueUserWorkItem(ThreadProc);
Console.WriteLine("From main foreground thread");
//Thread.Sleep(1000);
Console.WriteLine("Exiting from main");
}
static void ThreadProc(object stateInfo) {
Console.WriteLine("From the thread pool");
}
With Thread.Sleep(1000) uncommented it is sure that the background thread will complete before the main foreground thread exits. But when we comment the sleep part then also I get an output of sort:
From main foreground thread
Exiting from main
From the thread pool
It means that the background thread is still executed even when the main foreground thread has exited. Why so?
The end of the Main method doesn't mean the "foreground" thread has exited. Even if it has, it doesn't mean your process has terminated.
Normally, a process stops when all threads that run in the process (including the ones from the thread-pool, which have queued work) terminate. However, if you exit a process using ExitProcess. The CLR works in a slighly more complicated way (see here), which does quite some clean-up before really existing the application.
As a result, before all working threads get killed, there is pretty some time when work can get done.

How do I start a service thread using the TPL?

In the past, I've created the main thread of a service using the Thread object. Now I'm attempting to update it to the TPL. Unfortunately, the service ends after one pass in my loop. What do I need to do to keep the Task alive?
protected override void OnStart(string[] args)
{
_workerThread = Task.Run(() =>
{
while (true)
{
Console.WriteLine("go");
Thread.Sleep(10000);
}
});
}
More info:
In order to debug the service, I've set a flag to start the service as a console app if Environment.UserInteractive is set to true. So I guess I need it to keep going in console mode as well as a service.
When you create a new Thread, it is a foreground thread by default (its IsBackground is set to false). What that means is that your console application won't end until the thread does, even if Main returns before that.
Tasks, on the other hand, run on the thread pool, which contains only background threads. This means that when your Main returns, the application will exit, even if there is some Task still running.
You can fix this by Waiting on the Task at the end of your Main.

Does Thread.Sleep affect the ThreadPool?

I need to control one thread for my own purposes: calculating, waiting, reporting, etc...
In all other cases I'm using the ThreadPool or TaskEx.
In debugger, when I'm doing Thread.Sleep(), I notice that some parts of the UI are becoming less responsible. Though, without debugger seems to work fine.
The question is: If I'm creating new Thread and Sleep()'ing it, can it affect ThreadPool/Tasks?
EDIT: here are code samples:
One random place in my app:
ThreadPool.QueueUserWorkItem((state) =>
{
LoadImageSource(imageUri, imageSourceRef);
});
Another random place in my app:
var parsedResult = await TaskEx.Run(() => JsonConvert.DeserializeObject<PocoProductItem>(resultString, Constants.JsonSerializerSettings));
My ConcurrentQueue (modified, original is taken from here):
Creation of thread for Queue needs:
public void Process(T request, bool Async = true, bool isRecurssive = false)
{
if (processThread == null || !processThread.IsAlive)
{
processThread = new Thread(ProcessQueue);
processThread.Name = "Process thread # " + Environment.TickCount;
processThread.Start();
}
If one of the Tasks reports some networking problems, i want this thread to wait a bit
if (ProcessRequest(requestToProcess, true))
{
RequestQueue.Dequeue();
}
else
{
DoWhenTaskReturnedFalse();
Thread.Sleep(3000);
}
So, the question one more time: can Thread.Sleep(3000);, called from new Thread(ProcessQueue);, affect ThreadPool or TaskEx.Run() ?
Assuming that the thread you put on sleep was obtained from thread pool then surely it does affect the thread pool. If you explicitly say that the thread should sleep then it cannot be reused by the thread pool during this time. This may cause the thread pool to spawn new threads if there are some jobs awaiting to be scheduled. Creating a new thread is always expensive - threads are system resources.
You can however look at Task.Delay method (along with async and await) that suspends executing code in a more intelligent way - allowing the thread to be reused during waiting.
Refer to this Thread.Sleep vs. Task.Delay article.
Thread.Sleep() affects the thread it's called from, if you're calling Thread.Sleep() in a ThreadPool thread and trying to queue up more it may be hitting the max count of ThreadPool threads and waiting for a thread to finish before executing another.
http://msdn.microsoft.com/en-us/library/system.threading.threadpool.setmaxthreads.aspx
No, the Thread.Sleep() is only on the current thread. Thread.Sleep(int32) documentation:
The number of milliseconds for which the thread is suspended.

Sleep task (System.Threading.Tasks)

I need to create thread which will replace photo in Windows Forms window, than waits for ~1second and restore the previous photo.
I thought that the following code:
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
Thread.Sleep(1000);
pic.Image = Properties.Resources.PREV;
}, CancellationToken.None, TaskCreationOptions.LongRunning, ui)
do the job, but unfortunately doesn't. It freezes main UI thread.
That's because it's not guaranteed that there is one thread per one task. One thread can be used for processing several tasks.
Even TaskCreationOptions.LongRunning option can't help.
How I can fix it?
Thread.Sleep is a synchronous delay. If you want an asynchronous delay then use Task.Delay.
In C# 5, which is at present in beta release, you can simply say
await Task.Delay(whatever);
in an asynchronous method, and the method will automatically pick up where it left off.
If you are not using C# 5 then you can "manually" set whatever code you want to be the continuation of the delay yourself.
When you pass a new TaskScheduler that is from the current synchronization context, you actually telling the task to run on the UI thread. You actually want to do that, so you can update the UI component, however you don't want to sleep on that thread, since it will block.
This is a good example of when .ContinueWith is ideal:
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
EDIT (Removed some stuff and added this):
What happens is that we're blocking the UI thread for only enough time to update pic.Image. By specifying the TaskScheduler, you're telling it what thread to run the task on. It's important to know that the relationship between Tasks and Threads is not 1:1. In fact, you can have 1000 tasks running on relatively few threads, 10 or less even, it all depends on the amount of work each task has. Do not assume each task you create will run on a separate thread. The CLR does a great job of balancing performance automatically for you.
Now, you don't have to use the default TaskScheduler, as you've seen. When you pass the UI TaskScheduler, that is TaskScheduler.FromCurrentSynchronizationContext(), it uses the UI thread instead of the thread pool, as TaskScheduler.Default does.
Keeping this in mind, let's review the code again:
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
Here, we're creating and starting a task that will run on the UI thread, that will update the Image property of pic with your resource. While it does this, the UI will be unresponsive. Fortunately, this is a likely a very fast operation, and the user won't even notice.
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
With this code, we're calling the ContinueWith method. It does exactly what it sounds like. It returns a new Task object that will execute the lambda parameter when it runs. It will be started when the task has either completed, faulted or been cancelled. You can control when it will run by passing in TaskContinuationOptions. However, we're also passing a different task scheduler as we did before. This is the default task scheduler that will execute a task on a thread pool thread, thus, NOT blocking the UI. This task could run for hours and your UI will stay responsive (don't let it), because it's a separate thread from the UI thread that you are interacting with.
We've also called ContinueWith on the tasks we've set to run on the default task scheduler. This is the task that will update the image on the UI thread again, since we've passed that same UI task scheduler to the executing task. Once the threadpool task has finished, it will call this one on the UI thread, blocking it for a very short period of time while the image is updated.
You should be using a Timer to perform a UI task at some point in the future. Just set it to run once, and with a 1 second interval. Put the UI code in the tick event and then set it off.
If you really wanted to use tasks, you'd want to have the other task not run in the UI thread but rather in a background threat (i.e. just a regular StartNew task) and then use the Control.Invoke inside of the task to run a command on the UI thread. The problem here is that is' band-aid-ing the underlying problem of starting a task just to have it sleep. Better to just have the code not even execute in the first place for the full second.

Categories

Resources