After every Enqueue() all the values in the Queue become the same - c#

I'm receiving some data over a socket and trying to add it to a Queue so it can be dequeued by another thread that is much more slow, something like a buffer.
The problem is that everytime I enqueue a new value, all the values in the queue become that.
byte[] aux = new byte[1464];
aux = (byte[])ar.AsyncState;
//add the package to the package fifo list
lock (lockPktBuffer)
{
packetBuffer.Enqueue(aux);
}
First I thought that I was passing a pointer, so all the entries are just pointing to the same variable.
So I tried to do this:
lock (lockPktBuffer)
{
packetBuffer.Enqueue((byte[])ar.AsyncState);
}
But got the same problem.
Any ideia how to work this out ?

Here is what's going on (see the comments):
// This line creates a new array
byte[] aux = new byte[1464];
// This line "forgets" the new array, and replaces it with ar.AsyncState:
aux = (byte[])ar.AsyncState;
As the result of this, all additions to the queue happen to enqueue the same object returned from ar.AsyncState, producing the effect that you see (all instances in the queue look the same).
Here is how you can fix it:
byte[] aux = ((byte[])(ar.AsyncState).ToArray();
...
packetBuffer.Enqueue(aux);
This call makes a copy of ar.AsyncState into a new array of bytes, making sure that all instances that you enqueue are independent

You are passing a reference. When you assign an array to another, it's the reference that is copied, it doesn't copy the data in the array.
To make a copy of the array you need to specifically copy the data inside it. Example:
// get the reference to the source array
byte[] source = (byte[])ar.AsyncState;
// create a new array with the same size
byte[] aux = new byte[source.Length];
// copy all the values from the source
Array.Copy(source, aux, source.Length);

Related

Filling a list with random bytes

I'm trying to fill a buffer with random bytes. The buffer is defined as a list of bytes. This is something that I want to keep as it is. Here is the definition:
namespace NameofProject
{
public partial class Form1 : Form
{
List<byte> buff = new List<byte>();
}
}
And my first attempt is
public static void RandomFillBuffer()
{
Random rnd = new Random();
rnd.NextBytes(buff);
}
Yet this gives such an error for buff:
An object reference is required for the non-static field, method, or property 'Form1.buff'
Then I just deleted the word "static" (I am not sure whether this is true) and it becomes "public void RandomFillBuffer()", but this time I am getting this error for buff:
Argument 1: cannot convert from 'System.Collections.Generic.List' to 'byte[]'
I'd appreciate any help to solve any of the 2 errors if they make sense.
You're getting that problem because NextBytes() expects an array, but you're trying to pass a List<>. One way to solve it would be to change your List<> to an array:
byte[] buff = new byte[someSize];
You're going to have to figure out what someSize should be (it's up to you). You can't fill something without it having a size. Otherwise, how would it know when it's done?
The problem you are having is that NextBytes fills an array[] not a list. You need to define an array with an index of its size
// Put random bytes into this array.
byte[] array = new byte[8];
// Fill array with random bytes.
Random random = new Random();
random.NextBytes(array);
First: you tried to make your method static (it means that this method is not associated with any instance of the object but instead with the class of objects), and tried to reference not static member from it (your buff is not static and thus is associated with a particular instance, a particular Form in your case).
Second: you tried to use Random.NextBytes(System.Byte[]) but provided System.Collections.Generics.List<System.Byte> as an argument.
The code below should work for you (this code assumes at least that buff already has some data and so has a positive length):
var generator = new Random();
var array = new Byte[buff.Count]; // create a local array of the same size as your list
generator.NextBytes(array); // fill the array with random bytes
buff = array.ToList(); // copy array to a new list and let field "buff" reference this freshly created list
Please, note, that this code is not optimal because it copies an array. But it does what you want, I guess.

Store string data using an array (C#)

A task that I can't seem to solve, even after hours and hours of trying.
Basically, I have a phonebook that takes input from the user: name and number (both string type), which becomes a Contact.
I'm supposed to store the Contact in an Array, and the user shall both be able to add and also delete data (Contact) from the array, via the methods Create and Delete.
I made an own Repository class to handle the data (Contact also has an own little class), but I used List to store the data, so I could simply use Add and Remove, so my code looks like this:
public class Repository
{
List<Contact> storagelist;
public Repository() {
storagelist = new List<Contact>();
}
public void Create(Contact item) //Adds the item to the list
{
storagelist.Add(item);
}
public bool Delete(Contact item) //Removes the item
{
if (!storagelist.Contains(item))
return false;
storagelist.Remove(item);
return true;
}
}
What I am looking for, is how do exactly this, have these 2 features of adding and removing a Contact, but store the data in an Array instead.
Since arrays (to my knowledge) has to have a fixed, pre-defined size I have no idea how it could be used in exactly the same way as the List. The array size shall always be the same as the amount of Contacts that are stored, but how can this be done when an array's size is fixed??
So, how to create an array, that always has the same size as the amount of Contacts that are stored, and how to Add and Remove to/from this array?
Help is very much appreciated!
EDIT: Thanks for all responses! Every answer was helpful in the process (Omar and person66 in particular!).
I solved the Removal by "moving" the entire array after the delete-element, to 1 index lower, and finally resizing the array to be smaller. Like so:
int deleteIndex = Array.IndexOf(storagelist, item);
for (int index = deleteIndex + 1; index < storagelist.Length; index++)
{
storagelist[index - 1] = storagelist[index];
}
Array.Resize(ref storagelist, storagelist.Length - 1);
You are right in that array sizes are fixed. You can, however, use Array.Resize() to create a new array of the specified size with all the current array data. So for adding you would resize to 1 larger and add the new contact at the end. For removing you will have to use a loop to shift all the elements in the array past the one being removed back one spot, then resize it to be 1 smaller.
EDIT: A simpler option for removing would be to use Array.Copy():
Array.Copy(a, deleteIndex + 1, a, deleteIndex, a.Length - (deleteIndex + 1));
Array.Resize(ref a, a.Length - 1);
A list is a much better solution to this problem, I don't know why you would ever want to use an array for this.
A List just ends up using an array for it's storage anyway. The way a list works is it is initializes an array with a certain amount of storage then if it's capacity is exceeded it recreates an array with a larger size and copies the elements back. You could try this approach, except you'd just be recreating what a list does.
The other option is just declare an arbitrarily large array of 100,000 elements or so. A number which you know will not be exceeded.
For size you can write your own function which keeps track of the number of contacts in the array.
You can use a generic list. Under the hood the List class uses an array for storage but does so in a fashion that allows it to grow effeciently.
Take a look at this link for more details, it can be helpfull.
var contacts = new[]
{
new { Name = "Foo", Phone = "9999999999" },
new { Name = "Bar", Phone = "0000000000" }
};
You can create an array of anonymous object and then use linq to delete objects from array.
You can create a new object and insert into anonymous object variable.

Binary Formatter, Set Position to Deserialize Particular Object

I want to ask about serialize/deserialize object with binary formatter. well i'm trying to deserialize object in FileStream that contain many objects that has been serialized one by one. The size of an object is too big to be saved in process memmory that's why i don't pack all of objects in one such as: List because they are too big in process memory So i serialize as much as needed in many times. with this way it won't take many process memmory because i just process one object alternately not all of objects. take a look at sketch that i mean
<FileStream>
----Object 1-----Size = 100 Mb------index = 0
----Object 2-----Size = 100 Mb------index = 1
----Object 3-----Size = 100 Mb------index = 2
----Object 4-----Size = 100 Mb------index = 3
----Object 5-----Size = 100 Mb------index = 4
----Object 6-----Size = 100 Mb------index = 5
</FileStream>
Serialization object is also successfully now i got a problem to deserialized an object.
here is the problem:
in List we can take an item with index. so if we like to take fifth index we can call it such as:
List<object> list = new List<object>();
list(0) = "object1";
list(1) = "object2";
list(2) = "object3";
list(3) = "object4";
list(4) = "object5";
list(5) = "object6";
object fifthIndex = list[5]; // here we can get item based index
Well now the problem is how can i get objects with fifth index just like List Method on six Deserialization object in a filestream with Binary Formatter. i know in FileStream there is a property that named "FileStream.Position" but it does not like Index, it looks like a random number when i have deserialize/serialize an object. maybe it will increase random number.
actually i have succeeded with this but i bet this is not best way take a look at my code that i have ever tried:
object GetObjectStream(FileStream fs, int index)
{
if (fs != null)
{
BinaryFormatter binaryformatter = new BinaryFormatter();
bool isFinished = false; int count = 0;
while (isFinished == false)
{
try
{
object objectdeserialized = binaryformatter.Deserialize(fs);
if (count == index) return objectdeserialized;
count++;
}
catch
{
isFinished = true;
return null;
}
}
}
return null;
}
these codes will "foreach" every object that has been serialized and then deserialize every objects. i bet my codes are not the best way because to Deserialize object that contain 100 MB maybe it will take long time, I don't even know the object except index that ever be deserialized will be disposed or not? i want method just like a "Serialization Leap."
your answer is very helpfull and usefull for me if we can solve this problem.
Thanks before..
Each object will most likely take a different amount of space to serialize - data packs differently, especially for things like strings and arrays. Basically, to do this efficiently (i.e. without reading every object in full each time), you would want to either:
prefix each object with the amount of data it takes, by serializing it to a MemoryStream, storing the .Length (any way that is convenient to you; a 4 byte little-endian chunk would suffice), and then copy the data you wrote to MemoryStream to the output; then you can skip to the n'th item by n-times-(read 4 bytes as an int, skipping that many bytes)
in a separate index, store the .Position of the base stream just before you serialize each object; then to read the nth object, you use the index to find the position you need, and scroll to there
Actually, you were quite lucky here: BinaryFormatter isn't actually documented as being safe to append, but as it happens it does kinda work out ok it you do that - but this isn't true for all serialization formats.
Personally, though, I'd question whether there is simply a different design that could be used here.
----Write objects to file---
1. Keep a Dictionary<KeyType, long> dict. KeyType probably int if you key on an object number.
2. open file FileX for output; FileX.position = 0 at this point.
3. For each object:
update dictionary(oject.key, fileX.Position)
Serialize object to FileX (note: FileX.Position is updated by BinaryFormatter)
4. Close FileX. Save Dictionary (serialize to another file).
----Read Back Object---
Use Dictionary to get offset based on key of object you want:
do FileX.Seek(offset, 0); formatter.deserialize(FileX) to get back the
object you wish.

How can I convert a byte array to a string array?

Just to clarify something first. I am not trying to convert a byte array to a single string. I am trying to convert a byte-array to a string-array.
I am fetching some data from the clipboard using the GetClipboardData API, and then I'm copying the data from the memory as a byte array. When you're copying multiple files (hence a CF_HDROP clipboard format), I want to convert this byte array into a string array of the files copied.
Here's my code so far.
//Get pointer to clipboard data in the selected format
var clipboardDataPointer = GetClipboardData(format);
//Do a bunch of crap necessary to copy the data from the memory
//the above pointer points at to a place we can access it.
var length = GlobalSize(clipboardDataPointer);
var #lock = GlobalLock(clipboardDataPointer);
//Init a buffer which will contain the clipboard data
var buffer = new byte[(int)length];
//Copy clipboard data to buffer
Marshal.Copy(#lock, buffer, 0, (int)length);
GlobalUnlock(clipboardDataPointer);
snapshot.InsertData(format, buffer);
Now, here's my code for reading the buffer data afterwards.
var formatter = new BinaryFormatter();
using (var serializedData = new MemoryStream(buffer))
{
paths = (string[]) formatter.Deserialize(serializedData);
}
This won't work, and it'll crash with an exception saying that the stream doesn't contain a binary header. I suppose this is because it doesn't know which type to deserialize into.
I've tried looking the Marshal class through. Nothing seems of any relevance.
If the data came through the Win32 API then a string array will just be a sequence of null-terminated strings with a double-null-terminator at the end. (Note that the strings will be UTF-16, so two bytes per character). You'll basically need to pull the strings out one at a time into an array.
The method you're looking for here is Marshal.PtrToStringUni, which you should use instead of Marshal.Copy since it works on an IntPtr. It will extract a string, up to the first null character, from your IntPtr and copy it to a string.
The idea would be to continually extract a single string, then advance the IntPtr past the null byte to the start of the next string, until you run out of buffer. I have not tested this, and it could probably be improved (in particular I think there's a smarter way to detect the end of the buffer) but the basic idea would be:
var myptr = GetClipboardData(format);
var length = GlobalSize(myptr);
var result = new List<string>();
var pos = 0;
while ( pos < length )
{
var str = Marshal.PtrToStringUni(myptr);
var count = Encoding.Unicode.GetByteCount(str);
myptr = IntPtr.Add(myptr, count + 1);
pos += count + 1;
result.Add(str);
}
return result.ToArray();
(By the way: the reason your deserialization doesn't work is because serializing a string[] doesn't just write out the characters as bytes; it writes out the structure of a string array, including additional internal bits that .NET uses like the lengths, and a binary header with type information. What you're getting back from the clipboard has none of that present, so it cannot be deserialized.)
How about this:
var strings = Encoding.Unicode
.GetString(buffer)
.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

How to find empty bytes array

How to find out is bytes array has any data or it is newly created bytes array?
var Buffer = new byte[1000];
//How to find out is Buffer is empty or not?
I assume by 'empty' you mean containing default values for every byte element, if this isn't what you mean, look at #sehe's answer.
How about using LINQ to check whether all elements have the default value for the type:
var Empty = Buffer.All(B => B == default(Byte));
A byte is a valuetype, it cannot be null;
Creating an array immediately initializes the elements to the default value for the element type.
This means, empty cells can't exist, let alone be detected.
If you must:
use nullable types
var Buffer = new byte?[1000];
use Array.Resize when capacity changes. However, you could soon be in a situation where just using a System.Collections.Generic.List would be much more efficient
In addition to the answers given
var buffer = new byte[1000];
var bFree = true;
foreach (var b in buffer)
{
if (b == default(byte)) continue;
bFree = false;
break;
}

Categories

Resources