I need your help with using generic class and methods in C#. When I call EnqueObject method in ProduceData, on the line with EnqueueObject(block), an error occurs: cannot convert 'byte[]' to 'T'. I would appreciate any advice.
(I've simplified my code because I believe my problem is something really basic).
class CompressingProducer<T>
{
Queue<T> _queue;
public void ProduceData(object fileInputStream)
{
byte[] block = new byte[Settings.blockSize];
int bytesRead;
while ((bytesRead = ((Stream)fileInputStream).Read(block, 0, Settings.blockSize)) > 0)
{
EnqueueObject(block);
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(T data)
{
_queue.Enqueue(data);
}
}
UPDATE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
namespace GZipTestProject
{
class CompressingProducer<T>
{
Thread _producerThread;
readonly object _lock;
Queue<T> _queue;
/// <summary>
/// Reads data in chunks (as byte[]) or as CompressedData objects from the file stream and inserts them into a queue
/// </summary>
/// <param name="fileInputStream">Connected to the file from which data will be read</param>
public CompressingProducer(Stream fileInputStream) {
_lock = ProducerConsumer<T>.getLock();
_queue = ProducerConsumer<T>.getQueue();
_producerThread = new Thread(ProduceData);
_producerThread.Start(fileInputStream);
}
/// Takes a file input stream parameter from which data will be read and put into a queue for a consumer.
/// The parameter of this method must be object because it will be passed as a delegate to a new thread.
public void ProduceData(object fileInputStream)
{
if (GZipTest.GetActionType() == ActionType.Compress) {
byte[] block = new byte[Settings.blockSize];
int bytesRead;
while ((bytesRead = ((Stream)fileInputStream).Read(block, 0, Settings.blockSize)) > 0)
{
if (bytesRead < block.Length)
{
byte[] block2 = new byte[bytesRead];
Array.Copy(block, block2, bytesRead);
block = block2;
}
EnqueueObject(block); // put the data block into the queue
block = new byte[Settings.blockSize];
}
}
private void EnqueueObject(T data) //byte[] block or CompressedData
{
lock (_lock)
{
while (_queue.Count >= Settings.maxQueueSize)
{
Monitor.Wait(_lock); // suspends the whole main thread of the application
}
_queue.Enqueue(data);
if (_queue.Count == 1)
{
// wake up any blocked dequeue, i.e. the consumer thread
Monitor.PulseAll(_lock);
}
}
}
}
}
I've understood you need a further explanation of how the program should work. It should be used for compression and decompression. At first, it reads a file by blocks (byte arrays), then compresses the blocks, puts them in objects of my own class CompressedData and serializes them into one file. During the decompression the objects are deserialized and the zipped byte arrays are decompressed into a new file. It uses producer-consumer pattern, so there is a "producer" putting elements in a queue, the queue itself and a "consumer" taking elemens and processes the required operation (compression/decompression). I want to use my class CompressingProducer as "producer" of both operations, compression and decompression, it means it enqueues byte arrays during compression, and objects of my class CompressedData during decompression. It's why I'm trying to use generics.