Remoting - Updating Textbox from server messages

G

Guest

Hello,

I'm writing a server client application and I'm having a terrible time
getting one section to work. This is my first time using .net remoting, so
please bear with me if I'm doing something incorrectly. To give a brief
layout of my program, the server side hosts a series of functions for running
tests, this server application will run on four separate boxes. My client
application has access to all four of the server applications, and sends jobs
to those server to complete. On my client form, there are text boxes,
representing status on the jobs from each of the four servers.

My problem is getting those text boxes to update from the form, I'm using a
remote object that the client creates. I have this object referenced in the
server and it has one function.. SendMessage(string message)... When the
client recieves that message, I need it to update the text box in my Form
class. I've tried several different ways, but I keep running into Cross
Threading errors, or my program completely locks up. I've tried using
Events, but those still didn't seem to work.

Does anyone have any advice? I just purchased a book that will hopefully
help (Advanced Remoting (using C#)), I'm looking forward to recieving it and
hopefully it's full of great advice. In the meantime, I have a job to do and
I'm stuck.

Thanks for any help!

Cory B.
 
G

Galcho[MCSD.NET]

I supose the problem is in cross-threading operation.
This means that you cannot modify control in other thread that that
created control.
you can use delegates as workaround

Hope this helps

Galin Iliev[MCSD.NET]
www.galcho.com
 
G

Guest

Could you give an example of this? I played around with the delegates, but I
wasn't sure exactly how it worked. Would the delgate be placed in the remote
object or the class that contains the text box?
 
G

Galcho[MCSD.NET]

see here
there is example in folder %installation folder%\Data
Access\Asynchronous Queries

http://www.microsoft.com/downloads/...f8-033d-420b-a3b1-3074505c03f3&displaylang=en


this is code from there
//declare delegate
private delegate void DisplayInfoDelegate(string Text);


/// <summary>
/// This method displays the user message text that occurs during
processing
/// and after processing completes
/// </summary>
/// <param name="Text"></param>
private void DisplayResults(string Text)
{
this.messageReturned.Text = Text;

}

//call like this in method
DisplayInfoDelegate myUserDelegate = new
DisplayInfoDelegate(DisplayResults);
myUserDelegate(userMessage);


hope this helps

Galin Iliev[MCSD.NET]
www.galcho.com
 
G

Guest

Thanks for the reply, I downloaded those code samples, but I was unable to
find this specific example that you've given. I understand what your doing
there, but how am I able to access that delegate from a different class?
That's where I'm getting confused. Here is an example of what I'm doing.

//Remote Client Object

public class CallBackObject : MarshalByRefObject
{

public void ClientReciever(string msg, int Source)
{
//this needs to call Form1 and update the text box
Form1.UpdateText(msg); //I know this won't work, just for
reference...
}
}

public class Form1 : Form
{
public void UpdateTest(string message)
{
tbTest.AppendText(message + "\r\n");
}
}

I'm not quite sure where the delegates would go and how to call them from
one class to another. Could you point me in the right direction?

Thanks,

Cory B.
 
G

Galcho[MCSD.NET]

Hi Brosto,
this is code that should work according me:

public class CallBackObject : MarshalByRefObject
{
//probably keep reference to opened form
Form1 frm;

//declare delegate
private delegate void DisplayInfoDelegate(string Text);

public void ClientReciever(string msg, int Source)
{
DisplayInfoDelegate displayInfo = new
DisplayInfoDelegate(frm.UpdateTest);
displayInfo(msg);
}
}

public class Form1 : Form
{
public void UpdateTest(string message)
{
tbTest.AppendText(message + "\r\n");
}
}


if you have any problems just post here and we will try to resolve
them.

I hope this helps
Galin Iliev[MCSD.NET]
www.galcho.com
 
G

Guest

Hi Galcho,

Thank you for all your help on this, I really do appreciate it.

When I use the code you just gave me, I recieve the following error:

System.ArgumentException was unhandled by user code
Message="Delegate to an instance method cannot have null 'this'."
Source="mscorlib"
StackTrace:
at System.MulticastDelegate.ThrowNullThisInDelegateToInstance()
at System.MulticastDelegate.CtorClosed(Object target, IntPtr methodPtr)
at RegressionControlPanel.CallBackObject.ClientReciever(String msg,
Int32 Source) in D:\Visual Studio
2005\Projects\RegressionControlPanel\RegressionControlPanel\RemoteObject.cs:line 22
at
System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr
md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext,
Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle
md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext,
Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)


If I create a new instance of form1, then the update does not show on the
form I'm trying to update. Is there a way I can get "frm" to reference to my
active form?

Thanks!

Cory B.
 
G

Galcho[MCSD.NET]

I think the problem with this could be resolved as passing frm
reference as parameter - just as msg,
other solutions is go get it from outside - for instance some other
class could keep reference for you and when you receive callback from
server you ask other class for active form and perform update on it

I think second solution is much better.

I hope this helps
Galin Iliev[MCSD.NET]
www.galcho.com
 
G

Guest

Hi Galin,

I used the starting class that creates the form instanace and made a public
static instance of Form1 (see code below..) However, I'm back to square one
with the same error message I was recieving before:

Cross-thread operation not valid: Control 'tbTest' accessed from a thread
other than the thread it was created on.

I can't pass the form as a reference in the parmeter because the server
would not have a reference to that object. This could be some easy solution
and I'm just not seeing it. Unfortunetly where I work, no one else really
knows C# so I don't have a goto person for advice. Let me know if you have
anymore idea's on how to get around this. Thanks for all the help!

Cory B.

static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
public static ServerTalk ST = new ServerTalk();
public static Form1 _Form1;

[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_Form1 = new Form1();
Application.Run(_Form1);
}

}

partial class Form1 : Form
{
private void UpdateTestBox()
{
tbTest.AppendText(TestMessage + "\r\n");
}
}

public class CallBackObject : MarshalByRefObject
{
//declare delegate
private delegate void DisplayInfoDelegate(string Text);

public void ClientReciever(string msg, int Source)
{
DisplayInfoDelegate displayInfo = new
DisplayInfoDelegate(Program._Form1.UpdateTest);
displayInfo(msg);
}
}
 
G

Guest

Hi Galin,

Thanks for the reply... I have looked at the sample you posted, but I was
unable to get anyhwhere with it. They're doing something a little different
than what I'm doing. What I'm trying to do seems so simple, but it's been a
real pain so far. Anyhow, I've made a sample project with a client, server
and the remote objects. If you run them, you should get the same cross
threading errors that i was recieving. Let me know what you think.

Thanks,

Cory B.
 
G

Galcho[MCSD.NET]

I do not see the project.
there is nothing in my mail too.

Send it to me and I will check

Regards
Galin Iliev[MCSD.NET]
 
G

Guest

I believe I may have figured it out.

On my callback method, I used the Form.BeginInvoke method:

Object args = msg;
DisplayInfoDelegate displayInfo = new
DisplayInfoDelegate(Program.x.UpdateTest);
Program.x.BeginInvoke(displayInfo, args);

This seems to work and doesn't lock up the UI at all. Thanks for all your
help!

-Cory B.
 

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