This example is based on writing a file from asynchronously received TCP packets.  FileStream->Write is not thread safe, so this approach deals with letting file write occur in the background and waiting for it to complete before writing the next received block of data bytes.

In your header file


	FileStream ^ClientRxFileStream1;
	IAsyncResult ^ClientRxFileStreamAsyncResult1;
	array<Byte> ^ClientReceiveFileWriteBytes;

Receiving the first packet of bytes


	//Create the file to write to
	ClientRxFileStream1 = gcnew FileStream(ClientRxFilename, FileMode::Create, FileAccess::Write, FileShare::None);

	//Copy rx data to memory so it can be written to the file in the background
	ClientReceiveFileWriteBytes = gcnew array<Byte>(so->bufSize);
	Array::Copy(so->message, DataStart, ClientReceiveFileWriteBytes, 0, so->bufSize);

	//Write it to the file in the background
	ClientRxFileStreamAsyncResult1 = ClientRxFileStream1->BeginWrite(ClientReceiveFileWriteBytes, 0, so->bufSize, nullptr, nullptr);

Receiving subsequent packets of bytes


	if (ClientRxFileStream1 != nullptr)
	{
		if (ClientRxFileStreamAsyncResult1 != nullptr)
		{
			ClientRxFileStreamAsyncResult1->AsyncWaitHandle->WaitOne(10000);	//Block current thread until operation completes, timeout in mS

			ClientRxFileStream1->EndWrite(ClientRxFileStreamAsyncResult1);		//Last step to the write

			if (ClientRxFileStreamAsyncResult1->IsCompleted)					//Make sure the write really completed.
			{
				//Copy rx data to memory so it can be written to the file in the background
				ClientReceiveFileWriteBytes = gcnew array<Byte>(Convert::ToInt32(Size));
				Array::Copy(so->message, 0, ClientReceiveFileWriteBytes, 0, Convert::ToInt32(Size));

				//Write it to the file in the background
				ClientRxFileStreamAsyncResult1 = ClientRxFileStream1->BeginWrite(ClientReceiveFileWriteBytes, 0, Convert::ToInt32(Size), nullptr, nullptr);
			}
			else
			{
				//ERROR HERE!
			}
		}
	}

Once All Bytes Received


	if (ClientRxFileStreamAsyncResult1 != nullptr)
	{
		ClientRxFileStreamAsyncResult1->AsyncWaitHandle->WaitOne(10000);	//Block current thread until operation completes, timeout in mS
		ClientRxFileStream1->EndWrite(ClientRxFileStreamAsyncResult1);
	}

	ClientRxFileStream1->Close();
	ClientRxFileStream1 = nullptr;
	ClientRxFileStreamAsyncResult1 = nullptr;

Working Example Of Doing It With Multiple Clients

In your .h file

	using namespace System::Collections::Generic;

	ref class ClientRxFileStreamHandler
	{
	public:
		property String ^IpAddress;
		property String ^FileName;
		DateTime ClientLastActivity;
		FileStream ^ClientRxFileStream;
		IAsyncResult ^ClientRxFileStreamAsyncResult;
		array ^ClientReceiveFileWriteBytes;
	};

	List<ClientRxFileStreamHandler^> ^OurClientRxFileStreamHandlers;
In your .c file

//***********************
//***** CONSTRUCTOR *****
//***********************
	OurClientRxFileStreamHandlers = gcnew List(0);

//***********************************
//***** GOT NEXT PACKET OF DATA *****
//***********************************
	//----- FIND THIS CLIENTS FILE STREAM HANDLER OR CREATE A NEW ONE FOR IT -----
	Index = -1;
	for (Count = 0; Count < OurClientRxFileStreamHandlers->Count; Count++)		//If we already have this client then overwrite it
	{
		if ((OurClientRxFileStreamHandlers[Count]->IpAddress == ClientIpAddress) && (OurClientRxFileStreamHandlers[Count]->FileName == FileName))
		{
			//----- EXISTING CLIENT -----
			Index = Count;

			//Ensure last write has completed
			if ((OurClientRxFileStreamHandlers[Index]->ClientRxFileStream != nullptr) && (OurClientRxFileStreamHandlers[Index]->ClientRxFileStreamAsyncResult != nullptr))
			{
				OurClientRxFileStreamHandlers[Index]->ClientRxFileStreamAsyncResult->AsyncWaitHandle->WaitOne(10000);	//Block current thread until operation completes, timeout in mS
				OurClientRxFileStreamHandlers[Index]->ClientRxFileStream->EndWrite(OurClientRxFileStreamHandlers[Index]->ClientRxFileStreamAsyncResult);		//Last step to the write
			}
			break;
		}
	}
	if (Index == -1)
	{
		//----- NEW CLIENT -----
		OurClientRxFileStreamHandlers->Add(gcnew ClientRxFileStreamHandler);
		Index = OurClientRxFileStreamHandlers->Count - 1;

		OurClientRxFileStreamHandlers[Index]->IpAddress = ClientIpAddress;
		OurClientRxFileStreamHandlers[Index]->FileName = FileName;
	}
	OurClientRxFileStreamHandlers[Index]->ClientLastActivity = DateTime::Now;

	//----- QUICKLY CHECK FOR REMOVING ANY OLD CLIENTS THAT HAVE VANISHED -----
	DateTime RemoveBeforeDateTime = DateTime::Now - TimeSpan(0, 5, 0);		//We delete clients > 5 mins since last activity
	for (Count = 0; Count < OurClientRxFileStreamHandlers->Count; Count++)		//If we already have this client then overwrite it
	{
		if (OurClientRxFileStreamHandlers[Count]->ClientLastActivity < DeleteBeforeDateTime)
		{
			//REMOVE THIS CLIENT FROM THE ARRAY
			OurClientRxFileStreamHandlers[Count]->ClientRxFileStream->Close();
			OurClientRxFileStreamHandlers[Count]->ClientRxFileStream = nullptr;
			OurClientRxFileStreamHandlers[Count]->ClientRxFileStreamAsyncResult = nullptr;

			OurClientRxFileStreamHandlers->RemoveAt(Count);
			Count--;
		}
	}

	if ((ClientRxFilename != "") && (DataLength > 0))
	{
		if (File::Exists(ClientRxFilename))
		{
			System::IO::FileInfo ^FileInfo1 = gcnew System::IO::FileInfo(ClientRxFilename);
			FileSize = FileInfo1->Length;
		}
		else
		{
			FileSize = 0;
		}

		if (DataStart == FileSize)		//Data start must match the current file size
		{
			//----- WRITE THE FILE DATA -----
			if (OurClientRxFileStreamHandlers[Index]->ClientRxFileStream == nullptr)
			{
				if (FileSize == 0)
					OurClientRxFileStreamHandlers[Index]->ClientRxFileStream = gcnew FileStream(ClientRxFilename, FileMode::Create, FileAccess::Write, FileShare::None);
				else
					OurClientRxFileStreamHandlers[Index]->ClientRxFileStream = gcnew FileStream(ClientRxFilename, FileMode::Append, FileAccess::Write, FileShare::None);
			}
			
			OurClientRxFileStreamHandlers[Index]->ClientReceiveFileWriteBytes = gcnew array<Byte>(RxLength - PacketDataStart);
			Array::Copy(RxData, PacketDataStart, OurClientRxFileStreamHandlers[Index]->ClientReceiveFileWriteBytes, 0, (RxLength - PacketDataStart));

			OurClientRxFileStreamHandlers[Index]->ClientRxFileStreamAsyncResult = OurClientRxFileStreamHandlers[Index]->ClientRxFileStream->BeginWrite(OurClientRxFileStreamHandlers[Index]->ClientReceiveFileWriteBytes, 0, (RxLength - PacketDataStart), nullptr, nullptr);

			Success = true;
		}
	}
	else if ((FileName != "") && (DataLength == 0))
	{
		//----- END OF FILE -----
		//Close it and remove client
		if (OurClientRxFileStreamHandlers[Index]->ClientRxFileStream != nullptr)
		{
			OurClientRxFileStreamHandlers[Index]->ClientRxFileStream->Close();
			OurClientRxFileStreamHandlers[Index]->ClientRxFileStream = nullptr;
			OurClientRxFileStreamHandlers[Index]->ClientRxFileStreamAsyncResult = nullptr;
			OurClientRxFileStreamHandlers->RemoveAt(Index);
		}
		Success = true;
	}
Feel free to comment if you can add help to this page or point out issues and solutions you have found. I do not provide support on this site, if you need help with a problem head over to stack overflow.

Comments

Your email address will not be published. Required fields are marked *