Я пытался решить это упражнение "Параллельное программирование" (на C #):
Зная, что класс Stream
содержит методы int Read(byte[] buffer, int offset, int size)
и void Write(byte[] buffer, int offset, int size)
, реализуйте в C # метод NetToFile
, который копирует все данные, полученные из экземпляра NetworkStream net
, в экземпляр FileStream file
. Чтобы выполнить передачу, используйте асинхронное чтение и синхронную запись, избегая блокировки одного потока во время операций чтения. Передача заканчивается, когда операция чтения net
возвращает значение 0. Для упрощения нет необходимости поддерживать контролируемую отмену операции.
void NetToFile(NetworkStream net, FileStream file);
Я пытался решить это упражнение, но я борюсь с вопросом, связанным с самим вопросом. Но сначала вот мой код:
public static void NetToFile(NetworkStream net, FileStream file) {
byte[] buffer = new byte[4096]; // buffer with 4 kB dimension
int offset = 0; // read/write offset
int nBytesRead = 0; // number of bytes read on each cycle
IAsyncResult ar;
do {
// read partial content of net (asynchronously)
ar = net.BeginRead(buffer,offset,buffer.Length,null,null);
// wait until read is completed
ar.AsyncWaitHandle.WaitOne();
// get number of bytes read on each cycle
nBytesRead = net.EndRead(ar);
// write partial content to file (synchronously)
fs.Write(buffer,offset,nBytesRead);
// update offset
offset += nBytesRead;
}
while( nBytesRead > 0);
}
У меня вопрос в том, что в постановке вопроса сказано:
Для выполнения передачи используйте асинхронный
читает и синхронно пишет, избегая
один поток будет заблокирован во время чтения
операции
Я не совсем уверен, что мое решение выполняет то, что нужно в этом упражнении, потому что я использую AsyncWaitHandle.WaitOne()
, чтобы дождаться завершения асинхронного чтения.
С другой стороны, я не совсем понимаю, что в этом сценарии должно быть «неблокирующим» решением, поскольку запись FileStream
должна выполняться синхронно ... и делать это Мне нужно подождать, пока NetworkStream
чтение завершится, чтобы продолжить запись FileStream
, не так ли?
Не могли бы вы помочь мне с этим?
[РЕДАКТИРОВАТЬ 1] Использование Обратный вызов Решение
Хорошо, если я понял, что Митчел Селлерс и willvv ответили, мне посоветовали использовать метод обратного вызова, чтобы превратить это в "неблокирующее" решение. Вот мой код:
byte[] buffer; // buffer
public static void NetToFile(NetworkStream net, FileStream file) {
// buffer with same dimension as file stream data
buffer = new byte[file.Length];
//start asynchronous read
net.BeginRead(buffer,0,buffer.Length,OnEndRead,net);
}
//asynchronous callback
static void OnEndRead(IAsyncResult ar) {
//NetworkStream retrieve
NetworkStream net = (NetworkStream) ar.IAsyncState;
//get number of bytes read
int nBytesRead = net.EndRead(ar);
//write content to file
//... and now, how do I write to FileStream instance without
//having its reference??
//fs.Write(buffer,0,nBytesRead);
}
Как вы могли заметить, я застрял в методе обратного вызова, так как у меня нет ссылки на экземпляр FileStream
, где я хочу вызвать метод "Write (...)".
Кроме того, это не поточно-ориентированное решение, так как поле byte[]
открыто и может использоваться несколькими одновременными вызовами NetToFile
. Я не знаю, как решить эту проблему, не выставляя это поле byte[]
во внешней области видимости ... и я почти уверен, что оно не может быть открыто таким образом.
Я не хочу использовать лямбда-решение или решение с анонимным методом, потому что это не входит в программу курса "Параллельное программирование".