1

Consider having an application which creates 30 app-domains, then runs them (each app-domain in its own thread) and when each of these app-domains finishes running (aka its thread exits and so on) we need to cleanup by running for each appdomain some custom cleanup-logic + a call for unloading the appdomain itself.

The cleanup logic + appdomain-unloading call for each of these app-domains might require more than one attempts to succeed (due to resources being involved, taking time to be released by the system and so on). If the cleanup operation cannot be performed in a specific attempt, it doesn't take more than 100ms for us to know about this and move on.

What is the best practice, in the world of C#, to perform such cleanup in a 'perform-cleanup-in-the-background' fashion? Possible venues off the top of my head:

  1. Each app-domain cleanup should be performed in its very own 'new Thread()' corner. Each thread persists in a while loop with a sleep interval in case it needs to retry.

  2. Have just a single, dedicated long-running thread with a task-queue in which we submit each and every appdomain to be cleaned-up and unloaded (again in a persistent fashion like in method #1 above).

  3. Using a thread-pool and submitting the cleanup-tasks there

According to the following comment:

https://stackoverflow.com/a/28651533/863651

"If a method cannot be expected to exit within 100ms or so of when it starts execution, the method should be executed via some means other than the main thread pool.[ ... ] If, however, a method will take a second or longer to execute, and will spend most of its time blocked, the method should likely be run in a dedicated thread, and should almost certainly not be run in a main-threadpool thread."

I guess this discourages using method #3 above. I'm wondering if method#2 has any considerable advantages over method #1. The main thing that bugs me is that even though method#2 needs slightly more coding it uses just 1 thread no matter what, while method#2 will require N threads for N app-domains (with all the cost that this entails in terms of spawning the threads etc).

I'm open to suggestions about any method#4+ that there might be to implement such mechanism. I'm just curious to see how other programmers apply the concept of "best threading-practices" when it comes to such a problem.

Thanks in advance.

P.S.: This application is meant to be run in contemporary desktop computers (at the time of this writing).

Community
  • 1
  • 1
XDS
  • 3,786
  • 2
  • 36
  • 56
  • What cleanup operations need to be performed, and what determines when a given AppDomain needs to spin down? – Colin May 21 '15 at 21:18
  • Cleanup operations: Writing to a database (SQLite if it makes any difference) + deleting temporary files are just 2 standard tasks. An AppDomain enters the 'spin down' phase (aka becomes garbage-collection-worthy if I understand the wording correctly) when it has completed a series of tasks coded into it (displaying some c# dialogs, running dos commands, launching apps etc). These tasks are not fixed and vary from one appdomain to the next (the appdomains are generated dynamically). Hope this helps. – XDS May 21 '15 at 23:38

1 Answers1

1

Presuming you know what will need to be cleaned up at some point when you're managing the AppDomains, you can attach cleanup logic to the DomainUnload event like:

appDomain.DomainUnload += 
  (sender, args) => 
  {
       //this logic needs to be specific for each AppDomain.

       //you can consider using a class like BackgroundWorker to do the work.

  };

For the single vs. multi-thread question, as long as you make your code thread safe, then my take is that the multi-threaded option would both reduce the lines of code (always a goal of mine) and optimize performance, especially if running cleanup as a background thread. 10s of threads is really a non-issue as far as tapping out system resources (unless cleanup operations may exhaust memory). The main drawback is that multi-threaded programs can sometimes be trickier to debug, but I bet you'll be okay in this case.

Colin
  • 4,025
  • 21
  • 40
  • +1 for the DomainUnload bit. I'm still in limbo on whether the reduction in code-size justifies invoking 30 threads vS raising one thread but making the code more complex (usage of a queue, maintenance etc). – XDS May 22 '15 at 21:35
  • As long as you make the code thread safe, then my take is that you both reduce the lines of code (always a goal of mine) and optimize performance, especially if running cleanup as a background thread. 10s of threads is really a non-issue as far as tapping out system resources (unless cleanup operations may exhaust memory). The main drawback is that multi-threaded programs can sometimes be trickier to debug, but I bet you'll be okay in this case. – Colin May 23 '15 at 17:52
  • Would you be kind enough to copy-paste your comment into an answer-candidate? Just for the sake of keeping inline with the format of the site. – XDS May 28 '15 at 15:22