"System.ObjectDisposedException: Safe handle has been closed" when running a background thread
When using an ASP.NET page you may see the "System.ObjectDisposedException: Safe handle has been closed" when running a background thread.
Typically this is seen when you try to access the name property - for example.
Thread.CurrentPrincipal.Identity.Name
Unfortunately the thread identity is closed down and disposed of as part of this process so you can't access it.
To work around this problem it is possible to use clone the thread's CurrentPrincipal on the webform and pass this to the background thread and set to using the Thread.CurrentPrincipal property.
This is possible as the threads are running in the same process - this method wouldn't work across process boundaries.
/// <summary>
/// Occurs when the user
clicks the webform button, starting the long running background process/// </summary>
protected void Button1_Click(object sender, EventArgs e)
{
AutomationDelegate Delegate = new AutomationDelegate(BackgroundProcess);
WindowsIdentity Cloned = (WindowsIdentity)CloneObject(Thread.CurrentPrincipal.Identity);
Delegate.BeginInvoke(Cloned, null, null);
}
/// <summary>
/// The delegate to call/// </summary>
/// <param name="ThreadIdentity">The thread identity to be persisted to the background thread</param>
public delegate void AutomationDelegate(WindowsIdentity ThreadIdentity);
/// <summary>
/// The background process/// </summary>
/// <param name="ThreadIdentity">The threadidentity to persist</param>
void BackgroundProcess(WindowsIdentity ThreadIdentity)
{
Thread.CurrentPrincipal = new WindowsPrincipal(ThreadIdentity);
Log(Thread.CurrentPrincipal.Identity.Name);
Thread.Sleep(5000);
}
/// <summary>
/// Creates a clone of this
Configuration Type object/// </summary>
/// <param name="Source">The source object to clone</param>
public static Object CloneObject(Object Source)
{
MemoryStream Stream = new MemoryStream();
BinaryFormatter Formatter = new BinaryFormatter();
Formatter.Serialize(Stream, Source);
Stream.Position = 0;
object Clone = (object)Formatter.Deserialize(Stream);
Stream.Close(); Stream.Dispose();
return Clone;
}
Please let me know if you have any comments on this thread (no pun intended!)
ReplyDeleteThank you so much, this really saved my bacon :)
ReplyDeleteNo problems glad it helped :)
Delete