custom data types?

J

jodleren

I am still new, so I get stucked now and then.
As migrating from Delphi I have a few questions:

1) I have a Type, which use as a variable.
I want to ahve an array of 64 bytes as:

public void Whatever(TData stuff)
{
sdafsdf = stuff[4]; // TData is byte[64]

2) Same, but with a record of mixed variables:

public void Whatever(TData stuff)
{
string sdafsdf = stuff[4].name;
int sdafsdf = stuff[4].age;

3) delegates
Something as simple as TNotifyEvent - ?

4) threading
In Delphi there is "synchronize" - a way to "call" an event elsewhere.
It is done by adding a message to windows - meaning my thread will
continue, and the called procedure will be called when windows passes
the message on.
Can I do the same?
 
W

Willem van Rumpt

1) I have a Type, which use as a variable.
I want to ahve an array of 64 bytes as:

public void Whatever(TData stuff)
{
sdafsdf = stuff[4]; // TData is byte[64]

Assuming in Delphi you have type definitions along the lines of

type
T64BytesArray = array [0..63] of byte;

Then the answer is no. C# Doesn't allow those kinds of declarations.

You either have to have the method accept a byte array, and perform
bounds checks within that method, or you'll have to define a custom
class or struct which internally defines an array of that size, and
enforces access to it to be within those bounds.
2) Same, but with a record of mixed variables:

public void Whatever(TData stuff)
{
string sdafsdf = stuff[4].name;
int sdafsdf = stuff[4].age;

The same principle applies here. If the type declaration of TData is
something like:

type
TMyStuff = record
name: string;
age: Integer;
end;

TData = array [0..4] of TMyStuff;

then it won't work without you building a custom class or struct.

If you're ok with accepting an array (or list, collection) of arbitrary
length, then both in case 1) and 2), you could just use any array, list
or collection, and do the bounds checks in the method. If you don't wish
to check for them in every method, you'll have to wrap them in a
separate class (and deal with out-of-bounds accesses there).
3) delegates
Something as simple as TNotifyEvent - ?

The basic event system is almost similar to Delphi: You declare a field
(an "event" in C#), which type is of a procedural type (a delegate in
C#). When "something" happens, you check if the field is assigned, and
invoke the assigned method:

{Delphi}

type
TCallback = procedure(sender: TObject; data: TSomeData) of object;

TEventRaiser = class
private
....
FCallback: TCallback;
....
public
SomethingHappened: TCallback read FCallback write FCallback;
end;

....

// somewhere in the class implementation...
if (FCallback <> nil) then FCallback(self, <....>);

{C#}
public delegate void Callback(object sender, EventArgs e);

public class EventRaiser
{
....
public event Callback SomethingHappened;
....
}



// somewhere in the class implementation...
if (SomethingHappened != null)
{
SomethingHappened(this, <....>);
}


This is the basic pattern. You can read up on it here:

http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspx
4) threading
In Delphi there is "synchronize" - a way to "call" an event elsewhere.
It is done by adding a message to windows - meaning my thread will
continue, and the called procedure will be called when windows passes
the message on.
Can I do the same?

Synchronize in Delphi is mostly (ab)used to update the UI thread from
another thread (as a side note: IIRC "Synchronize" does /not/ just post
a message to the message queue; it posts the message and blocks the
calling thread until the posted message gets handled, making it as evil
as the "Application.ProcessMessages" method).

Pete suggested several possible solutions specifically for exactly that
scenario: BackgroundWorker and/or Control.Invoke. You can learn more
about them here:

http://msdn.microsoft.com/en-us/library/8xs8549b.aspx

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
 
A

Arne Vajhøj

I am still new, so I get stucked now and then.
As migrating from Delphi I have a few questions:

1) I have a Type, which use as a variable.
I want to ahve an array of 64 bytes as:

public void Whatever(TData stuff)
{
sdafsdf = stuff[4]; // TData is byte[64]

Make TData a class that encapsulate a byte[] with
proper accesors and mutators.

2) Same, but with a record of mixed variables:

public void Whatever(TData stuff)
{
string sdafsdf = stuff[4].name;
int sdafsdf = stuff[4].age;
Same.

3) delegates
Something as simple as TNotifyEvent - ?

I think we need more explanation.
4) threading
In Delphi there is "synchronize" - a way to "call" an event elsewhere.
It is done by adding a message to windows - meaning my thread will
continue, and the called procedure will be called when windows passes
the message on.

I think this must be the same as Invoke in .NET Win Forms.

Arne
 
J

jodleren

1) I have a Type, which use as a variable.
I want to ahve an array of 64 bytes as:
public void Whatever(TData stuff)
{
    sdafsdf = stuff[4]; // TData is byte[64]

Assuming in Delphi you have type definitions along the lines of

type
   T64BytesArray = array [0..63] of byte;

Then the answer is no. C# Doesn't allow those kinds of declarations.

You either have to have the method accept a byte array, and perform
bounds checks within that method, or you'll have to define a custom
class or struct which internally defines an array of that size, and
enforces access to it to be within those bounds.

Rest snipped. The array of byte as a paremeter is working, and
probably saves memory.

Thank to you all and especially this answer. Here I found what I need
and go it to work, though I still have a few things to go though, but
the main point is that I got my test app working, the programme is
(almost) working as expected. (btw, communicating with hardware).
My questions are still general, as I am new here, I am not always able
for formulate my questions properly yet. Sometimes I dont know what to
look for.

I will still have to look at the invoke command, and - streaming.
I receive data from a com port, which comes in parts - hence I need to
take what I have, and keek the rest until next time.

Someone told me, that keeping a (memoy?)stream is better than a
string. I failed to create a proper stream today :(
My data is !RD 1 2 3\r - when I have \r I have data, and need to split
it.
That will be for tomorrow.

Finally, thanks for the help-

Sonnich
 
J

jodleren

If you're using the SerialPort class, and your data is in some encoded
text format (e.g. ASCII, UTF-8, etc.), then I think the simplest
approach might be to use StreamReader.  For example:

   SerialPort port = …; // initialized however you like
   StreamReader reader = new StreamReader(port.BaseStream);
   string line;

   while ((line = reader.ReadLine()) != null)
   {
     SomeMethodThatHandlesALineOfTest(line);
   }

Use one of the StreamReader overloads that lets you specify the text
encoding if it's something other than the default (UTF-8).

This can be done in a worker thread if you need it to perform
asynchronously.  As suggested earlier, you can use Control.Invoke() or
similar to deal with updating the GUI based on the work.

As far as MemoryStream being better than a String, that depends entirely
on what you're doing.  But in general, it would be true that if you're
concatenating data as it's received, using a String instance isn't going
to be as efficient as either MemoryStream (if you're reading bytes) or
StringBuilder (if you're reading characters).

Pete

Hmmm... I seem to have another problem - data from the COM port is
hazy.
While I should get !DATA 0 1 2...\r I get a !DAT!DATA0DADATAATA
blabla.
The problem is both with my my string example and the stream example
here. I have limited my programme to one command and one module only,
so there should be no option of other devices talking. A delay of 1
second has been added to ensure enough time.

This means, that the problem is my comport / receiving part which
causes the problem.

My code is as yours above - setting up COM, adding stream, handlind
data as you do above (in the received event)

Any ideas?

Sonnich
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top