I've been using this program.
I am currently running the server program in an appdomain. However, when I want to unload it, it returns an exception with HRESULT 0x80131015. This only occurs when I start the pipeServer by clicking the button. I've checked which threads are running and tried to abort them, but they just won't abort. Their status comes back as "abort requested."
public void Start(string pipename)
{
PipeName = pipename;
//start the listening thread
listenThread = new Thread(ListenForClients)
{
IsBackground = true
};
listenThread.Start();
Running = true;
}
void ListenForClients()
{
SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
// set the Security Descriptor to be completely permissive
InitializeSecurityDescriptor(ref sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false);
IntPtr ptrSD = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
Marshal.StructureToPtr(sd, ptrSD, false);
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES
{
nLength = Marshal.SizeOf(sd),
lpSecurityDescriptor = ptrSD,
bInheritHandle = 1
};
IntPtr ptrSA = Marshal.AllocCoTaskMem(Marshal.SizeOf(sa));
Marshal.StructureToPtr(sa, ptrSA, false);
while (true)
{
// Creates an instance of a named pipe for one client
SafeFileHandle clientHandle =
CreateNamedPipe(
PipeName,
// DUPLEX | FILE_FLAG_OVERLAPPED = 0x00000003 | 0x40000000;
0x40000003,
0,
255,
BUFFER_SIZE,
BUFFER_SIZE,
0,
ptrSA);
//could not create named pipe instance
if (clientHandle.IsInvalid)
continue;
int success = ConnectNamedPipe(clientHandle, IntPtr.Zero);
//could not connect client
if (success == 0)
{
// close the handle, and wait for the next client
clientHandle.Close();
continue;
}
Client client = new Client
{
handle = clientHandle
};
lock (clients)
clients.Add(client);
Thread readThread = new Thread(Read)
{
IsBackground = true
};
readThread.Start(client);
}
// free up the ptrs (never reached due to infinite loop)
Marshal.FreeCoTaskMem(ptrSD);
Marshal.FreeCoTaskMem(ptrSA);
}
void Read(object clientObj)
{
Client client = (Client)clientObj;
client.stream = new FileStream(client.handle, FileAccess.ReadWrite, BUFFER_SIZE, true);
byte[] buffer = new byte[BUFFER_SIZE];
while (true)
{
int bytesRead = 0;
using (MemoryStream ms = new MemoryStream())
{
try
{
// read the total stream length
int totalSize = client.stream.Read(buffer, 0, 4);
// client has disconnected
if (totalSize == 0)
break;
totalSize = BitConverter.ToInt32(buffer, 0);
do
{
int numBytes = client.stream.Read(buffer, 0, Math.Min(totalSize - bytesRead, BUFFER_SIZE));
ms.Write(buffer, 0, numBytes);
bytesRead += numBytes;
} while (bytesRead < totalSize);
}
catch
{
//read error has occurred
break;
}
//client has disconnected
if (bytesRead == 0)
break;
//fire message received event
if (MessageReceived != null)
MessageReceived(ms.ToArray());
}
}
// the clients must be locked - otherwise "stream.Close()"
// could be called while SendMessage(byte[]) is being called on another thread.
// This leads to an IO error & several wasted days.
lock (clients)
{
//clean up resources
DisconnectNamedPipe(client.handle);
client.stream.Close();
client.handle.Close();
clients.Remove(client);
}
// invoke the event, a client disconnected
if (ClientDisconnected != null)
ClientDisconnected();
}
This is some sample code which runs the two background threads. Any help on how to unload the appdomain safely?
User contributions licensed under CC BY-SA 3.0