all groups > dotnet remoting > july 2005 >
You're in the

dotnet remoting

group:

Socket is freezing my datagrid


Socket is freezing my datagrid Edge
7/26/2005 12:00:00 AM
dotnet remoting:
hi,

we here have an app where the server push some data assynch to the
clients connected via tcp socket. This data is then captured in the
client and inserted in a datagrid. So far no problem.
But sometimes, when the incoming data is in a too short period, my
client freezes.

any hints on this? should I implement any 'wait' mechanism in my client
or server?

TIA
Re: Socket is freezing my datagrid Mehdi
7/26/2005 11:39:01 AM
[quoted text, click to view]

Are you sure that you are always accessing your datagrid (which is a UI
Control) only from the UI thread in which it has been created and not from
a worker thread. If you try to access your Datagrid from a worker thread,
it's gonna freeze randomly (UI controls are not thread safe and should only
be accessed from the UI thread).

On the other side, if you are not using worker thread to read data on your
socket but doing everything in the UI thread, then you'll have freezes too
since the whole UI is gonna freeze whenever you'll wait for data to arrive
Re: Socket is freezing my datagrid Edge
7/28/2005 12:00:00 AM
[quoted text, click to view]

Hi,
I found the problem for this case. I just had to call the update method
within a BeginInvoke method.


Re: Socket is freezing my datagrid edge
8/11/2005 12:00:00 AM
hi
thanks for your reply.
Actually I was thinking I found a solution, but yes, it is freezing
randomically.
I do not know about this worker thread.
Do I have to follow any guideline to update my UI control?
any sample code that I can see?

and as far as I know I am not implementing any thread in my app. Please
advice.

TIA
-Edge



[quoted text, click to view]

Re: Socket is freezing my datagrid edge
8/12/2005 12:00:00 AM

[quoted text, click to view]

Great hints!
Well, seems that it is working, but instead of calling the new MethodInvoker
I am using a delegate. Please look at how i am doing:

in my ClientForm.cs I have this class:
public class MyCallbackClass : RemotelyDelegatableObject
{
private ClientForm mainChild = null;
public MyCallbackClass (ClientForm pMain) { mainChild = pMain ; }
protected override void InternalSubmissionCallback (object sender,
RemoteEventArgs e)
{
try
{
//mainChild is my client form, UpdateClient is the workerThread
//I think here is the secret. I must call a threadsafe method to update
my grid.
//FYI, I was doing mainChild.AddRowToDataGrid( e.MyStringData ) and it
was freezing
mainChild.UpdateMyClient( e.MyStringData );
}
catch( Exception ex )
{
//mainChild.listbox2.Items.Add(
ex.Message+"-"+ex.Source+"-"+ex.InnerException.Message );
}

}

and my ClientForm has this:
public void UpdateMyClient( string data )
{
// I created a delegate called SetIncomingDataTextDelegate
this.Invoke( new SetIncomingDataTextDelegate( AddRowToDataGrid ), new
object[] { data } );
// AddRowToDataGrid inserts the data string feed into the datagrid
}

a few more questions:
Is this the way it should be? is it a valid alternative?
Also I noticed that the client form is acting a little slow when I
drag-and-move it in my screen. maybe because the listening?
at first I was trying to use BeginInvoke() with no success, looks like the
correct way it is Inkove();

TIA
-Edge

Re: Socket is freezing my datagrid Mehdi
8/12/2005 9:05:02 PM
[quoted text, click to view]

There are 3 situation where your code can be executed within a worker
thread:
1) you manually create a new Thread and start it. This is apparently not
what you are doing
2) you are queuing your methods in the threadpool queue so that they get
executed in one of the ThreadPool thread. This is probably not what you are
doing either since you would know that you are using threads if you had
done that
3) you are starting an asynchronous operation and supplying a callback
method that gets executed once the asynchronous operation has completed.
This callback is always executed within a worker thread. The Socket class
provides such methods (BeginConnect, BeginSend, BeginReceive...). If you
are using them, then you are in a multi-threaded situation.

In order to safely update your datagrid from a worker thread, you should
marshall the call to the method that accesses your datagrid to the UI
thread (the thread where all the UI controls of your application have been
created). You can do that by using either the Invoke or BeginInvoke method
of the Control class.

Say that you have a control called uiControl (this can be anything, your
form, your datagrid, anything as long as it derives from the Control
class). Here is the code to do what you want safely:

void UpdateDatagrid()
{
// Here do whatever you want
// with your Datagrid
}

void WorkerThreadMethod()
{
// This is the method executing
// in a worker thread where
// you want to update the datagrid

// Marshall the call to UpdateDatagrid() to the
// UI thread
uiControl.Invoke(new MethodInvoker(UpdateDatagrid));
}

One important thing here is that the Invoke method relies on uiControl to
have a valid Handle in order to properly marshall the call to the UI
thread. So you should make sure that uiControl has a valid handle. You can
be sure that uiControl has a valid Handle if it has been displayed on the
Re: Socket is freezing my datagrid Mehdi
8/14/2005 12:00:00 AM
[quoted text, click to view]

MethodInvoker is actually just a normal delegate provided for your
convenience in the .NET framework.

[quoted text, click to view]

Yes, it looks alright to me. Something that i like to do, but this is
purely for aestetical reasons, is to put the marshalling code and the
actual UI code in a single method. In your code, you've got the
AddRowToDataGrid method that modifies your datagrid and the UpdateMyClient
method that just marshall the call to AddRowToDataGrid to the UI thread.
You could rewrite it with a single method like that:

public void UpdateMyClient( string data )
{
if (this.InvokeRequired)
{
// We are in a workder thread,
// let's marshall ourself to the UI thread
this.Invoke( new SetIncomingDataTextDelegate( UpdateMyClient ), new
object[] { data } );
}
else
{
// We are now in the UI thread, let's update
// this datagrid
// Put the code that was in AddRowToDataGrid here
}
}



[quoted text, click to view]

There are many reasons that could cause the form to be slow to repaint
itself. It could be because the CPU is too busy or because you are doing
some long running operations in the UI thread, hence preventing the thread
from being able to repaint your controls when the form is moved.

[quoted text, click to view]

BeginInvoke should work. The only difference between Control.Invoke and
Control.BeginInvoke is that Invoke blocks until the invoked method has
completed while BeginInvoke returns immediately. But the invoked method
Re: Socket is freezing my datagrid edge
8/15/2005 12:00:00 AM
Great. Indeed, it passed through the test this weekend. Next step is to put
a similar behavior in the SQL.

My server (winform) calls a method called SendMsgToClient( string message,
int channelID ) to deliver the data string to the connected clients. Can I
do the same call via stored procedure using the OA objects?
I used regasm to generate the typelib and placed my RemoteServer.dll in the
GAC but the message was not sent to the client.
have you done something similar to it? any ideas how to accomplish this?

namespace WRemoteServer
{
public delegate void RegisterEventHandler (object sender, RemoteEventArgs
e);

public class RemoteServer : MarshalByRefObject
{
public static event RegisterEventHandler InvokeHostForm;
public event RegisterEventHandler InvokeCallbackMethod,
InvokeCallbackMethod2;

public void RemoteServerMethod(string str, out string strOut)
{
RemoteEventArgs e = new RemoteEventArgs(str);

if(InvokeHostForm != null)
InvokeHostForm(this, e);

strOut = str + " Returned from Server!";
}
public void SendMsgToClient(string str, int msg)
{
RemoteEventArgs e = new RemoteEventArgs(str);
// Fire Client Event
if (InvokeCallbackMethod != null && (msg == 1 || msg==0))
InvokeCallbackMethod(this, e);
else if (InvokeCallbackMethod2 != null && (msg == 2 || msg==0))
InvokeCallbackMethod2(this, e);
}
// This is to insure that when created as a Singleton, the first instance
never dies,
// regardless of the time between users messages.
public override object InitializeLifetimeService()
{
return null;
}
}

public abstract class RemotelyDelegatableObject : MarshalByRefObject
{
public void SubmissionCallback (object sender, RemoteEventArgs submitArgs)
{
try
{
InternalSubmissionCallback (sender, submitArgs) ;
}
catch{}
}

protected abstract void InternalSubmissionCallback (object sender,
RemoteEventArgs submitArgs) ;
}

[Serializable]
public class RemoteEventArgs : EventArgs
{
public string SendMessage;
public string usrName, srvType;
public RemoteEventArgs(string msg)
{
this.SendMessage = msg;
}
public RemoteEventArgs(string msg, string name, string type)
{
this.SendMessage = msg;
this.usrName = name;
this.srvType = type;
}
}
}




[quoted text, click to view]
AddThis Social Bookmark Button