I have pretty simple code like:
var childDomain = AppDomain.CreateDomain("child");
childDomain.ExecuteAssembly("WpfApplication1.exe");
AppDomain.Unload(childDomain);
But it closes app at all. I don't have any references to WpfApplication1.exe in parent app. I read this - AppDomain Unload killing Parent AppDomain but it hadn't helped.
So what I'm doing wrong?
The problem was in this line:
childDomain.ExecuteAssembly("WpfApplication1.exe");
ExecuteAssembly method runs application on the same thread as caller. So unloading is killing the main thread. The solution is run child app in new STA thread.
Related
I need to do a lot of work in UI thread. This work consumes a lot of CPU and memory resources. In current realization I use Dispatcher.BeginInvoke() method, but it makes my application frozen.
What if I will delegate this job to child process without GUI? Main process run child process. After that main application sends some commands to child process, child process do some job and returns result object to host process?
How to communicate between host and child processes? I know about .NET remoting (marshaling), but it obsolete method (or not?).
Thanks and sorry for my bad english.
I've made a child process management library where the parent process and the child process are monitored due a bidirectional WCF pipe. If either the child process terminates or the parent process terminates each other is notified.
There is also a debugger helper available which automatically attaches the VS debugger to the started child process
You have a extendable communication infrastructure between the processes. No need for WCF knowledge.
Project site:
http://www.crawler-lib.net/child-processes
NuGet Packages:
https://www.nuget.org/packages/ChildProcesses
https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/
I have a window (C#) application (only .exe file, no code) which uses a thread.
If my application is closed mean I am not using that application.
Is thread working backword at this time or not?
My Problem is that I am transferring a file from one drive to another drive at a particular time using timer thread class, at that particular time application is closed.
File will transfer or not?
No it wont. The thread was started in application and if application is closed all threads in it are killed.
Any threads that you start in your program, prevent the application from terminating, until all the treads have exited their thread proc function, or have abort() called on them.
To examine the exact way the timer thread class works, run the demo code that is located on the MSDN
http://msdn.microsoft.com/en-GB/library/ms149618.aspx
As people have pointed out, set background threads will not prevent application from termination, however, having a thread as a background thread, would not achieve what the op wanted.
No, threads only exist if your application is running. You need to create a completely separate background process (not just a background thread) if you want something to continue after your main application exits
I read on MSDN that the difference between a foreground thread and a background thread is that an application can't terminate until all of its foreground threads have terminated, whereas it won't bother waiting for background threads. I decided to try this out just to get a better understanding of threads.
Thread t = new Thread(Work); //Work() just has the thread sleep for a long time
t.IsBackground = false; //make it a foreground thread
t.Start();
while(true)
{
if(Session["checker"] != null)
{
Session["checker"] = true;
System.Diagnostics.Debug.Write("I'm here!");
}
}
I used a session variable to know if the AppDomain has been restarted since sessions get cleared upon an AppDomain restart.
So when I save the web.config file, it should trigger the AppDomain to restart, which should require it to wait for my long running thread t since t is running in the foreground. However when I touch the web.config file, goes straight into clearing my Session["checker"] and printing out "I'm here!", so I know that my application didn't wait for my thread.
Am I misunderstanding how foreground threads are supposed to work? Shouldn't the AppDomain restart wait for my thread to finish executing before it goes and starts clearing my session variables?
Thanks
Please, pay attention to the word "application" in statement "application can't terminate until all of its foreground threads have terminated". In case of recycling, application is not terminated. During recycling ASP.NET is unloading old AppDomain and loading new one. Everything is done inside single process. Process isn't terminated. In scope of AppDomain unloading, all threads (Background and Foreground) are killed.
So, ASP.NET won't wait for foreground threads to complete during recycling.
Try simple console application which creates a Foreground thread in its Main method. It will work until the thread is terminated.
A DLL process is running in an isolated App. Domain which was runned from a 3rd application.
I would like to unload AppDomain
If I use Enviroment.Exit(), it also kills the father application (app which lauches the DLL process)
edit
Doing as it follows neither:
AppDomain domainObj = AppDomain.CurrentDomain;
AppDomain.Unload(domainObj);
If a function from the DLL is running as a thread in a separate AppDomain in your process, then you can try calling AppDomain.Unload. According to the documentation,
When a thread calls Unload, the target domain is marked for unloading. The dedicated thread attempts to unload the domain, and all threads in the domain are aborted. If a thread does not abort, for example because it is executing unmanaged code, or because it is executing a finally block, then after a period of time a CannotUnloadAppDomainException is thrown in the thread that originally called Unload. If the thread that could not be aborted eventually ends, the target domain is not unloaded. Thus, in the .NET Framework version 2.0 domain is not guaranteed to unload, because it might not be possible to terminate executing threads.
So if you are unable to successfully unload this other appdomain - you may have to find other alternatives.
I have a Application which copies a DLL (UserControlLibrary) to its own Debug/Release folder and loads it using this Code:
AppDomain appDomain = AppDomain.CreateDomain("MyDomain");
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "DLLs (*.dll)|*.dll";
if (dialog.ShowDialog().Value)
{
string newLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + dialog.SafeFileName;
File.Copy(dialog.FileName, newLocation, true);
Assembly assembly = appDomain.Load(AssemblyName.GetAssemblyName(newLocation));
UserControl userControl = (UserControl) assembly.CreateInstance("WpfControlLibrary1.UserControl1");
}
I now add that UserControl to a Grid using:
grid.Children.Add(userControl);
Works fine. Now I try to unload the DLL using:
AppDomain.Unload(appDomain);
grid.Children.Clear();
If I now try to load the DLL (because it changed meanwhile) again using the above code I get an error telling me the file is in use (File.Copy).
I've read a lot of things and my guess is that I'm not allowed to use the UserControl like I did (because that loads into the Main AppDomain). How do I have to change the Code to make it work?
I've also read a lot of things about using MarshalByRefObject but unfortunately I was unable to implement it in this project. A example or modification of the code above would be nice.
EDIT:
From the comments I've read so far (especially from svick) it looks like I have to use "AppDomain.CreateInstanceAndUnwrap" instead of "AppDomain.Load".
I've seen that approach already while searching for a solution earlier but as svick mentioned that doesn't work because a UserControl can't inherit from MarshalByRefObject.
Does anyone know another way?
Read the documentation for AppDomain.Load(). It specifically says that this method loads the assembly both into the assembly you are calling the method on and into the current assembly. So, even when you unload the app domain, the assembly still stays loaded in the current assembly.
I'm not sure there is a way around this as you can't make UserControl inherit from MarhshalByRefObject.
When you call unload, the AppDomain is not immediately unloaded (see MSDN for the full article):
When a thread calls Unload, the target domain is marked for unloading.
The dedicated thread attempts to unload the domain, and all threads in
the domain are aborted. If a thread does not abort, for example
because it is executing unmanaged code, or because it is executing a
finally block, then after a period of time a
CannotUnloadAppDomainException is thrown...
Perhaps this quote from the MSDN article for AppDomain.Unload could explain things:
In the .NET Framework version 2.0 there is a thread dedicated to unloading application domains. This improves reliability, especially when the .NET Framework is hosted. When a thread calls Unload, the target domain is marked for unloading. The dedicated thread attempts to unload the domain, and all threads in the domain are aborted. If a thread does not abort, for example because it is executing unmanaged code, or because it is executing a finally block, then after a period of time a CannotUnloadAppDomainException is thrown in the thread that originally called Unload. If the thread that could not be aborted eventually ends, the target domain is not unloaded. Thus, in the .NET Framework version 2.0 domain is not guaranteed to unload, because it might not be possible to terminate executing threads.
Maybe there are some rogue threads that are keeping the app domain alive and therefore also keeping your file locked.
As a workaround, you could copy the DLLs to random file names instead.