question life time of an asynchronous thread...

K

Keyee Hsu

Hi, I have a C# app that creates an AppDomain, enters it, and spawns an
asyn thread to do some work and then block itself. Upon the completion
of the work, the async thread supposedly terminates, then the original
thread unblocks, unloads the AppDomain, and starts the whole process all
over again. I get the System.AppDomainUnloadedException saying that the
AppDomain from which the async thread resides has been unloaded. Now,
if I were to add a Thread.Sleep() command before the main thread returns
and unloads the AppDomain, then everything ran fine. I include the
program below hoping someone would shed some lights on this.

Thanks!


// program begins....

using System;
using System.Reflection;
using System.Threading;

namespace adSample
{
delegate void appDomainDelegate();

class asyncAD: MarshalByRefObject
{
private static AutoResetEvent evtWorkDone = new
AutoResetEvent(false);

[STAThread]
static void Main(string[] args)
{
try
{
for (int ix=0; ix<5; ++ix)
{
AppDomain AD =
AppDomain.CreateDomain("monitorAppDomain", null, null);
asyncAD ad = (asyncAD)AD.CreateInstanceAndUnwrap
(

Assembly.GetCallingAssembly().FullName,

"adSample.asyncAD"
);

ad.wrkStart();

Console.WriteLine("unloading AD\r\n");
AppDomain.Unload(AD);
} // for()
}
catch (AppDomainUnloadedException ex)
{
Console.WriteLine( "caught: {0}", ex.Message );
}

Console.WriteLine("Press Enter to quit the sample\r\n");
Console.ReadLine();
} // Main

//
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void wrkStart()
{
appDomainDelegate dlgtAD = new
appDomainDelegate(wrkSpinoff);

/*
// case 1 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);
while (!iAR.IsCompleted)
{
Thread.Sleep(100);
} // while()

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
*/

/*
// case 2 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
Thread.Sleep(1000);
*/

/*
// case 3 ==================>
System.AppDomainUnloadedException
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
*/

/*
// case 4 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(new
AsyncCallback(wrkCallback),

dlgtAD);

evtWorkDone.WaitOne();
Thread.Sleep(1000);
*/

/*
*/
// case 5 ==================>
System.AppDomainUnloadedException
IAsyncResult iAR = dlgtAD.BeginInvoke(new
AsyncCallback(wrkCallback),

dlgtAD);

evtWorkDone.WaitOne();

Console.WriteLine("exiting from: {0}",
Thread.GetDomain().FriendlyName);
} // wrkStart()

//
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void wrkSpinoff()
{
Console.WriteLine("in wrkSpinoff()");

for (int ix=0; ix<5; ++ix)
{
Console.WriteLine(ix);
Thread.Sleep(500);
} // for(ix)

Console.WriteLine("exiting wrkSpinoff()");
} // wrkSpinof()

//
-------------------------------------------------------------------
private void wrkCallback(IAsyncResult ar)
{
Console.WriteLine("in wrkCallback()");
appDomainDelegate dlgt = (appDomainDelegate)ar.AsyncState;

dlgt.EndInvoke(ar);

Console.WriteLine("exiting wrkCallback()");
evtWorkDone.Set();
} // wrkCallback()

} //asyncAD
} // adSample
 
T

Tim Matteson

I was able to run through 20 plus iterations without a crash by modifieing
your wrkCallBack method:

private void wrkCallback(IAsyncResult ar)
{
Console.WriteLine("in wrkCallback()");
appDomainDelegate dlgt = (appDomainDelegate)ar.AsyncState;

evtWorkDone.Set();
dlgt.EndInvoke(ar);

Console.WriteLine("exiting wrkCallback()");

} // wrkCallback()

Before your were calling EndInvoke then Set, what I believe was happening
(I'm not up to par yet on some aspects of threading) is that you were
calling EndEnvoke which released your WaitOne in wrkStart, then calling Set
trying to signal the tread (at which point, wrkStart had exited, and maybe
even tried to unload the AppDomain). So random mayem resulted.

Let me know if that fixes it,

Tim

Keyee Hsu said:
Hi, I have a C# app that creates an AppDomain, enters it, and spawns an
asyn thread to do some work and then block itself. Upon the completion
of the work, the async thread supposedly terminates, then the original
thread unblocks, unloads the AppDomain, and starts the whole process all
over again. I get the System.AppDomainUnloadedException saying that the
AppDomain from which the async thread resides has been unloaded. Now,
if I were to add a Thread.Sleep() command before the main thread returns
and unloads the AppDomain, then everything ran fine. I include the
program below hoping someone would shed some lights on this.

Thanks!


// program begins....

using System;
using System.Reflection;
using System.Threading;

namespace adSample
{
delegate void appDomainDelegate();

class asyncAD: MarshalByRefObject
{
private static AutoResetEvent evtWorkDone = new
AutoResetEvent(false);

[STAThread]
static void Main(string[] args)
{
try
{
for (int ix=0; ix<5; ++ix)
{
AppDomain AD =
AppDomain.CreateDomain("monitorAppDomain", null, null);
asyncAD ad = (asyncAD)AD.CreateInstanceAndUnwrap
(

Assembly.GetCallingAssembly().FullName,

"adSample.asyncAD"
);

ad.wrkStart();

Console.WriteLine("unloading AD\r\n");
AppDomain.Unload(AD);
} // for()
}
catch (AppDomainUnloadedException ex)
{
Console.WriteLine( "caught: {0}", ex.Message );
}

Console.WriteLine("Press Enter to quit the sample\r\n");
Console.ReadLine();
} // Main

//
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void wrkStart()
{
appDomainDelegate dlgtAD = new
appDomainDelegate(wrkSpinoff);

/*
// case 1 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);
while (!iAR.IsCompleted)
{
Thread.Sleep(100);
} // while()

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
*/

/*
// case 2 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
Thread.Sleep(1000);
*/

/*
// case 3 ==================>
System.AppDomainUnloadedException
IAsyncResult iAR = dlgtAD.BeginInvoke(null,
null);

// Call EndInvoke to retrieve the results.
dlgtAD.EndInvoke(iAR);
*/

/*
// case 4 ==================> OK
IAsyncResult iAR = dlgtAD.BeginInvoke(new
AsyncCallback(wrkCallback),

dlgtAD);

evtWorkDone.WaitOne();
Thread.Sleep(1000);
*/

/*
*/
// case 5 ==================>
System.AppDomainUnloadedException
IAsyncResult iAR = dlgtAD.BeginInvoke(new
AsyncCallback(wrkCallback),

dlgtAD);

evtWorkDone.WaitOne();

Console.WriteLine("exiting from: {0}",
Thread.GetDomain().FriendlyName);
} // wrkStart()

//
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void wrkSpinoff()
{
Console.WriteLine("in wrkSpinoff()");

for (int ix=0; ix<5; ++ix)
{
Console.WriteLine(ix);
Thread.Sleep(500);
} // for(ix)

Console.WriteLine("exiting wrkSpinoff()");
} // wrkSpinof()

//
-------------------------------------------------------------------
private void wrkCallback(IAsyncResult ar)
{
Console.WriteLine("in wrkCallback()");
appDomainDelegate dlgt = (appDomainDelegate)ar.AsyncState;

dlgt.EndInvoke(ar);

Console.WriteLine("exiting wrkCallback()");
evtWorkDone.Set();
} // wrkCallback()

} //asyncAD
} // adSample
 
K

Keyee Hsu

Thanks, Tim, yes that seems to fix the problem for case #5. A couple of
things with this scenario, though. One, case #3 still fails without the
callback being used. Second, for case #5, the main thread in wrkStart()
does not continue until the event is set (EndInvoke() itself doesn't
unblock the main thread), so by setting the event before the the
EndInvoke() call in wrkCallback(), it should have caused the main thread
to unblock even sooner and thus unloads the AppDomain even earlier.
Which, I think, should've made the problem worse, not fixing it like it
did. So, I'm even more perplexed now as to what happened behind the
scenes 8-(. What do you think?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top