Я пытаюсь решить это упражнение "Параллельное программирование" (на С#):
Зная, что класс
Stream
содержит методыint Read(byte[] buffer, int offset, int size)
иvoid Write(byte[] buffer, int offset, int size)
, реализует в С# метод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
, не так ли?
Можете ли вы помочь мне в этом?
[EDIT 1] Использование решения обратного вызова
Хорошо, если я понял, что Mitchel Sellers и 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[]
во внешней области... и я почти уверен, что это может быть не показано таким образом.
Я не хочу использовать решение лямбда или анонимного метода, потому что это не в учебном плане курса "Параллельное программирование".