Re: Threading Faux Pa

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



/*
Hmmm... I'm not sure how much I can give you in a 'brief' description.
:)

Esentially, there is a collection of objects like the parent object in
my first post. When the application starts up, The collection grabs all
the Parent class data from the database and loads all the objects.
After all the objects are loaded, the collection then loops through all
the objects in the collection and starts the communications - Lets say
a TCPClient that is wrapped in a 'communicator' class. We are not
limited to TCPClient, (i.e. we have a serial driver, a TCPServer
communicator, a dialup communicator etc) but it seems to be the most
sensitive because it's uses the BeginRecieve callback method. As I
mentioned, if everything is processed synchronously, loading takes a
considerable amount of time. I added a thread (_thrMyThread) to the
Parent class that gets started and loads the communicator and then
suspends - as expressed in LoadCommunicator() and InitComms(). Moving
the communications loading to the new thread improved load times
tremendously.Unfortuantely, I really don't think this is the best
solution and I am running into thread abort errors (i.e. if the comms
are still busy when _thrMyThread ends, exceptions are thrown).

Logic Flow:

1) Start the collection
2) Load all the 'Parent' objects
3) Begin loading communications
4) In LoadCommunicator, start a thread and launch the communicator
initialization and startup on the thead, then suspend it when complete
5) When exiting a parent object call dispose, which resumes the
thread - causing it to terminiate.


NOTES:
1) I hand coded this so any syntax errors are not important, the real
code compiles...
2) Any missing class members are un-important, just pretend you know
what they are...
3) ParentCollection just extends CollectionBase and returns Parent
objects
4) Syntax is a little messy as I inherited the real code form some that
did think standard
syntax or error handling is important :-{

Hope this is a little more explicit

Russ
p.s. Please feel free to email me directly if you need more info...
*/

public class ObjectModelController
{
ParentCollection _pcMyColl = new ParentCollection();

public ObjectModelController()
{

Parent objParent;

DataReader reader = MakeBelieveGetDataFunction();

//Loop through data and Create all instances of Parent object
while(reader.Read())
{
objParent = new Parent(reader[0],reader[1],reader[2]);

_pcMyColl.Add(objParent);
}

//This is where we load the communications. This part of the
processing is what takes so long
// if done synchronously
for(int i = 1; i <_pcMyColl.Count; i++)
{
//Loads defaults and comms settings
_pcMyColl[i].LoadCommunicator();
}
}

public void Shutdown()
{
for(int i = 1; i < _pcMyColl.Count; i++)
{
_pcMyColl[i].CloseComms();

_pcMyColl[i].Dispose();
}
}
}

/******************************************************************************************/
public class Parent
{
private Thread _thrMyThread;

private MyTCPClientWrapper _clsMyWrapper;

private MyCommsWrapper _cwCommunicator;
public Communicator
{
get
{return _cwCommunicator;}
set
{_cwCommunicator = value;}
}

public Parent()
{ //The object model needs to be loaded before the constructor
//exits
LoadObjectModel();
}

private void LoadObjectModel()
{
//Load Object here
}

private void LoadCommunicator()
{
//Load the thread object and start it
_thrMyThread = new Thread(new
ThreadStart(InitCommunications));
_thrMyThread.Start();
}

//This is called by the thread that is started in the
LoadCommunicator Function
private void InitCommunications()
{
this.Communicator = new MyCommsWrapper("args");

if(this.Communicator.ConnectOnStartup)
{
this.Communicator.StartComms();
}

//stops the thread from dropping out and finishing
_thrMyThread.Suspend();
}

public void Dispose()
{
if(_thrMyThread.ThreadState ==
ThreadState.Suspended)
{
_thrMyThread.Resume();
}
}
}
/*****************************************************************************************/
public class Communicator
{
public CommsProfile profile;

public bool ConnectionStatus;

public Communicator(string strArgs)
{
profile = new CommsProfile("args");
}
public abstract void AsyncWrite(string strMessageOut);
public abstract void StartComms();
public abstract bool CloseComms();

}

/************************************************************************************************/

public class TCPClientCommunicator: Communicator
{
TCPClient _tclClient;
NetworkStream _nsTCPStream;

public TCPCLientCommunicator(string strArgs)
{
//LOAD PROFILE HERE (ip, port, timeout)
profile = new TCPClientProfile('127.0.0.1', 8080, 600);
}

public override void StartComms()
{
_tclClient = new TcpClient(this.profile.ipAddress,
this.profile.portNumber);
LingerOption loDontLinger = new LingerOption(false,0);
_tclClient.LingerState = loDontLinger;

_nsTCPStream = _tclClient.GetStream();

_nsTCPStream.BeginRead(readBuffer, 0, READ_BUFFER_SIZE, new
AsyncCallback(DoRead), null);

CommStatusUpdate("Open");
this.ConnectionStatus = true;
}

private void DoRead (IAsyncResult ar)
{
int intCount;
try
{
if(_nsTCPStream != null)
{
lock(_nsTCPStream)
{
intCount = _nsTCPStream.EndRead(ar);
if (intCount < 1)
{
return;
}
//BuildString concatinates the data and then uses an event to send out
// data to other parts of the application then clears the buffer.
BuildString(readBuffer, 0, intCount);
_nsTCPStream.BeginRead(readBuffer, 0, READ_BUFFER_SIZE,new
AsyncCallback(DoRead), null);
}
}
}
catch (Exception ex)
{
l4nSystemLogger.Error(System.Reflection.MethodInfo.GetCurrentMethod().Name,
ex);
Debug.WriteLine(ex.Message);
}
}

public override AsyncWrite(string strMessage)
{
_tclClient.Write(strMessage);
}


public override bool CloseComms()
{
try
{
//If the client is valid...
if (_tclClient != null)
{

//Close and destroy the stream
_nsTCPStream.Close();
_nsTCPStream = null;

//Close and destroy the TCPClient
_tclClient.Close();
_tclClient = null;

//Turn Connection status to false -
this.ConnectionStatus = false;
CommStatusUpdate("Closed");

//THIS IS A BAND_AID THAT Pauses the processing
until
//the comms can close. Doesn't always work though.
Sometimes comms takes
// longer to close than the time I have set...
// I want a better way to do this
_thrMyThread.Join(500);
}
}
catch (Exception err)
{
System.Console.WriteLine(err.Message);
}
return true;
}

}

.



Relevant Pages

  • Re: Use a DC in a worker thread
    ... opportunities to update the progress bar, one for each little piece you did. ... typedef void ... CWnd * parent = NULL); ... static void SetRange; ...
    (microsoft.public.vc.mfc)
  • Re: Multiple Lines with a FlowLayout within a SOUTH region in a BorderLayout
    ... public static void main{ ... JPanel mainPanel = new JPanel; ... public void addLayoutComponent{ ... public Dimension preferredLayoutSize(Container parent) { ...
    (comp.lang.java.gui)
  • Re: [RFC][PATCH 3/3] sched: On-demand tg_shares_up()
    ... wide tree with a small number of active groups it should be a win. ... -static void update_shares(long cpu) ... If it has a parent, insert it immediately before the parent in the list. ...
    (Linux-Kernel)
  • Re: Cant copy the background of my simple control
    ... I made a simple control that should simply paint a dragable circle on ... correct background of the parent. ... void CSimpleCircleDrawer::OnPaint ... //Work out the new position (in parent client coordinates) ...
    (microsoft.public.vc.mfc)
  • C#/2.0: Tricky issue with generics.
    ... public class NodeList: ... NodeList can take a Node that is the parent. ... the case should be totally valid in my optinion. ...
    (microsoft.public.dotnet.languages.csharp)