How do I create single thread pool and execute Task on it?
Basically, I want Task.Run() to serialise all calls to be executed on one single thread.
Related
Currently I'm using a viewModelScope to launch a coroutine which in turns retrieves data from a remote server and caches the results in a local ROOM database.
My question is if I should use instead a GlobalScope to launch the coroutine to get such remote data, as the retrieval/caching can be interrupted if the app is sent to the background when using the viewModelScope.
Android discourages to perform continuous running tasks in the background since it uses battery and memory in the main thread. However, if you specifically need code to run in the background, consider using Background Services or Work Manager which is also responsible for starting background tasks.
Suppose we have a CommandPool with two CommandBuffers allocated from it (CommandBuffer1, CommandBuffer2).
The CommandPool lives on Thread 0, CommandBuffer1 and CommandBuffer2 also live on Thread 0.
Is it possible to transfer CommandBuffer1 and CommandBuffer1 to a different thread to record commands? With the restriction that only one thread is allowed the record a CommandBuffer at the same time?
The spec states
Command pools are application-synchronized, meaning that a command pool must not be used concurrently in multiple threads. That includes use via recording commands on any command buffers allocated from the pool, as well as operations that allocate, free, and reset command buffers or the pool itself.
I am not quite sure if I would be allowed to record CommandBuffer1 on Thread 1 and CommandBuffer2 on Thread 2 at the same time.
Or do I have to record all CommandBuffers on the same thread that they were allocated from?
There is a list of "Implicit Externally Synchronized Parameters" in chapter 2.5. Threading Behavior that has a list mostly consisting of:
The VkCommandPool that commandBuffer was allocated from, in vkCmd*
So no it's not possible to record 2 command buffers from the same pool on different threads.
Though it is strange that vkBeginCommandBuffer and vkEndCommandBuffer isn't in that list.
Who's forcing you to have only one pool though?
Have one pool per thread. Problem solved.
Yes, you do not have to use them on the same thread. You just must make sure that:
[...]command pool must not be used concurrently in multiple threads.
If you (for some obscure reason) want to use the pool on different thread, you must stop using it on the original thread (via using synchronization primitives) before you start using it on the second thread.
I have a simple thread pool written in pthreads implemented using a pool of locks so I know which threads are available. Each thread also has a condition variable it waits on so I can signal it to do work.
When work comes in, I pick a thread by looking finding an available thread from the lock pool. I then set a data structure associated with the thread that contains the work it needs to do and signal on the condition variable that the thread should start working.
The problem is when the thread completes work. I need to unlock the thread in the lock pool so it's available for more work. However, the controlling thread is the one which set the lock, so the thread can't free this lock itself. (And the controlling thread doesn't know when work is done.)
Any suggestions?
I could rearchitect my thread pool to use a queue where all threads are signaled when work is added so one thread can grab it. However, in the future, thread affinity will likely be a problem for incoming work and the lock pool makes implementation of this easier.
It seems to me that the piece of data that you're trying to synchronize access to is the free/busy status of each thread.
So, have a table (array) that records the free/busy status of each thread, and use a mutex to protect access to that table. Any thread (controller or worker) that wants to examine/change the thread status needs to seize the mutex, but the lock needs to be held only while the status is being examined/changed, not for the entire duration of the thread's work.
To assign work to a thread, you would do:
pthread_mutex_lock(&thread_status_table_lock);
-- search table for available thread
-- assign work to that thread
-- set thread status to "busy"
pthread_mutex_unlock(&thread_status_table_lock);
-- signal the thread
And when the thread finishes its work, it would change its status back to "free":
pthread_mutex_lock(&thread_status_table_lock);
-- set thread status to "free"
pthread_mutex_unlock(&thread_status_table_lock);
One feature of Threads is that you can set the .IsBackground property to true, and it will not prevent the process from terminating (ie, the framework calls Thread.Abort() on all running background threads at termination)
I can't seem to find a similar feature in Tasks. I used background threads a lot when I create services, where if the thread has not ended gracefully after the timeout period, the framework just kills it. This prevents the service manager from hanging getting into that weird task failed to stop scenario.
Is there a way to treat tasks as background? Or do I have to add the necessary code to abort tasks myself?
Tasks already run as background threads.
I would like to know how you would run a stored procedure from a page and just "let it finish" even if the page is closed. It doesn't need to return any data.
A database-centric option would be:
Create a table that will contain a list (or queue) of long-running jobs to be performed.
Have the application add an entry to the queue if, when, and as desired. That's all it does; once logged and entered, no web session or state data need be maintained.
Have a SQL Agent job configured to check every 1, 2, 5, whatever minutes to see if there are any jobs to run.
If there are as-yet unstarted items, mark the most recent one as started, and start it.
When it's completed, mark it as completed, or just delete it
Check if there are any other items to run. If there are, repeat; if not, exit the job.
Depending on capacity, you could have several (differently named) copies of this job running, concurrently processing items from the list.
(I've used this method for very long-running methods. It's more an admin-type trick, but it may be appropriate for your situation.)
Prepare the command first, then queue it in the threadpool. Just make sure the thread does not depend on any HTTP Context or any other http intrinsic object. If your request finishes before the thread; the context might be gone.
See Asynchronous procedure execution. This is the only method that guarantees the execution even if the ASP process crashes. It also self tuning and can handle spikes of load, requests are queued up and processed as resources become available.
The gist of the solution is leveraging the SQL Server Activation concept, which allows you to run a stored procedure in a background thread in SQL Server without a client connection.
Solutions based on SqlClient asynch methods or on CLR thread pool are unreliable, the calls are lost as the ASP process is recycled, and besides they build up in-memory queues of requests that actually trigger a process recycle due to memory consumption.
Solutions based on tables and Agent jobs are better, as they are reliable, but they lack the self tuning of Activation based solutions.