|
Thanks for the quick reply. I actually figured out the problem. May not be a problem after all, just the way .NET developers designed the library. There is a peculiar channel property called "machineName" which by default you shouln't have to worry about: http://msdn2.microsoft.com/en-us/library/kw7c6kwc(d=ide).aspx#machineName
Setting the property on the server to the current "outside" address solves the problem !!! Here is what I think happens:
When ShowText() is called, nothing special takes place b/c the client knows what to pass and what to get back. Done deal. With ShowFileInfo(), the FileInfo object can incurr additional calls from the client side. That is why in that case the server will return a message with a bunch of stuff and one of them being the server's ip address. Dont know whats the need for that, since the client already knows the server's ip address. But the server is "dumb" enough to put its local address in message, not the wan address. So setting "machineName" to the wan address of the server does the trick. Here is the soap message returned by the server to the client upon ShowFileInfo():
http://img185.imageshack.us/img185/1772/remotingtestworksfu1.png
Note how item id="ref-17 is now set to "igor.no-ip.ca:1024" as opposed to "10.0.0.1:1024". It makes sence now.
So here, in all glory is a working code:
----------------------------------------
Client:
<br />
using System;<br />
using System.Collections;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.Runtime.Remoting;<br />
using System.Runtime.Remoting.Channels;<br />
using System.Runtime.Remoting.Channels.Http;<br />
using System.IO;<br />
<br />
namespace RemotingTest<br />
{<br />
class Program<br />
{<br />
static void Main(string[] args)<br />
{<br />
IDictionary properties = new Hashtable();<br />
<br />
SoapClientFormatterSinkProvider clientSinkProvider = new SoapClientFormatterSinkProvider();<br />
SoapServerFormatterSinkProvider serverSinkProvider = new SoapServerFormatterSinkProvider();<br />
<br />
serverSinkProvider.TypeFilterLevel =<br />
System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;<br />
<br />
properties["name"] = "";<br />
properties["port"] = 0;<br />
properties["typeFilterLevel"] = "Full";<br />
<br />
HttpChannel commChannel = new HttpChannel(properties, clientSinkProvider, serverSinkProvider);<br />
<br />
ChannelServices.RegisterChannel(commChannel, false);<br />
<br />
RemotingConfiguration.RegisterWellKnownClientType(<br />
typeof(ServerInterface),<br />
"http://igor.no-ip.ca:1024/Server");
<br />
ServerInterface server = new ServerInterface();<br />
<br />
string text = "";<br />
<br />
while((text = Console.ReadLine()) != "Quit")<br />
{<br />
Console.WriteLine(server.ShowText("testing string"));<br />
Console.WriteLine(server.ShowFileInfo(text).Name);<br />
}<br />
<br />
Console.Read();<br />
}<br />
}<br />
}<br />
Server Interface:
-----------------------
<br />
using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.IO;<br />
<br />
namespace RemotingTest<br />
{<br />
public class ServerInterface: MarshalByRefObject <br />
{<br />
public FileInfo ShowFileInfo(string filename)<br />
{<br />
Console.WriteLine("Filename " + filename + " requested");<br />
<br />
return new FileInfo(filename);<br />
}<br />
<br />
public string ShowText(string text)<br />
{<br />
Console.WriteLine(text);<br />
<br />
return "\"" + text + "\" show on the server.";<br />
}<br />
}<br />
}<br />
Server:
-------------------
<br />
using System;<br />
using System.Collections;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.Runtime.Remoting;<br />
using System.Runtime.Remoting.Channels;<br />
using System.Runtime.Remoting.Channels.Http;<br />
<br />
namespace RemotingTest<br />
{<br />
class Program<br />
{<br />
static void Main(string[] args)<br />
{<br />
IDictionary properties = new Hashtable();<br />
<br />
SoapServerFormatterSinkProvider serverSinkProvider = new SoapServerFormatterSinkProvider();<br />
<br />
serverSinkProvider.TypeFilterLevel =<br />
System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;<br />
<br />
properties["name"] = "";<br />
properties["port"] = 1024;<br />
properties["typeFilterLevel"] = "Full";<br />
properties["machineName"] = "igor.no-ip.ca";
<br />
HttpChannel commChannel = new HttpChannel(properties, null, serverSinkProvider);<br />
<br />
ChannelServices.RegisterChannel(commChannel, false);<br />
<br />
RemotingConfiguration.RegisterWellKnownServiceType(<br />
typeof(ServerInterface),<br />
"Server", WellKnownObjectMode.SingleCall);<br />
<br />
Console.Read();<br />
}<br />
}<br />
}<br />
----------------------
Now its time for me to write an article on this. Having a router is quite common, and Im sure other programmers will stumble on the same problem.
Thanks for all you help guys!!
-- modified at 15:31 Friday 4th August, 2006
|
|
|
|
|
Okay, that's great! You still have a broken network and I would highly suggest you fix it before you go much further and I mean that seriously. Please don't be advising others on how something may work until you've tested it thoroughly on a functioning network.
- Rex
|
|
|
|
|
I did follow your guide and changed everything to the suggested settings. It was very detailed, thank you. It did not solve my problem though, but I am sure it will prevent me from having other network-related problems.
-- modified at 9:18 Saturday 5th August, 2006
|
|
|
|
|
Does anyone have an idea of how to get a DataGridView column to display as a button with an icon?
My current application displays just the icon, as an image, but it would be more obvious that the icons can be clicked and aren't just status icons if the cell containing them looked like a button. When I set the column type to Button, there does not appear to be any way to assign an image, only text, to a cell. So, is it possible to have a cell that is obviously a button which has an icon upon it?
I thought this would be a more common issue than it seems to be!
Thanks for your help!
|
|
|
|
|
Hi everybody, i used a thread to process a button function inside my code and because of that i used the showDialog function to open another forms from the thread, but i am trying to close the form i opend by using the ShowDialog function and it didnt work. How can i make an instance from the Active form i showed by the ShowDialog in order to close it later .
Any help please
Thanx
I hope that i am helping programmers
|
|
|
|
|
Ramez Quneibi wrote: used a thread to process a button function inside my code
Could you elaborate on that a little bit? My guess is your problem has something to do with threading. You cannot access a control on a thread other than the one it was created on.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Messianic Instrumentals (with audio)
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
Here i am showing you snippets from my code to elaborate on the problem to you
These snippets form Form1 class :
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
System.Threading.Thread NewFormMaker = new System.Threading.Thread(new System.Threading.ThreadStart(Dummy));
NewFormMaker.Start();
}
public static void Dummy()
{
Form2 fmNew = new Form2();
fmNew.ShowDialog();
}
This is a snippet from Form2 class :
// When this button pressed from Form2 this function should create new
// form with new controls and close the previous one
private void Next_Click(object sender, System.EventArgs e)
{
// Create an instance from the active form to close it
Form2 tempForm=(Form2)Form2.ActiveForm;
// Call Dummy() function from Form1 to show the new results
Form1.Dummy();
// Close the previous form with the old results
tempForm.Close();
}
The problem is that i cant make an instance from the active form to close it when i press button next from Form2.
Thanx
I hope that i am helping programmers
-- modified at 3:42 Tuesday 1st August, 2006
|
|
|
|
|
Ramez Quneibi wrote: he problem is that i cant make an instance from the active form to close it when i press button next from Form2.
OK, a couple things worth mentioning here. If you need to pass an instance of form1 over to form2, add an argument to the Form2 constructor that stores the form1 instance:
class Form2
{
readonly Form1 firstFormInstance;
public Form2(Form1 instance)
{
this.firstFormInstance = instance;
}
}
A second thing to note is that you cannot access a control or a form on a thread other than the one it was created on. Say you have Form1 instance created by "thread1". You start a new thread, "thread2" to launch a new Form2 instance. This is all valid, however, inside form2, you cannot access form1 because it was created by a different thread. If you need to do that, you'll need to use form1.Invoke or form1.BeginInvoke, which will invoke some method on the correct thread for form1.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Messianic Instrumentals (with audio)
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
I used these techniques you told me about ,it may work in other applications but it my code it didnt. I used another thread to show form2 from form1 but i didnt work because i am filling form2 from form1 class and if i make another thread i cant fill form2 from form1 class.
Anyways...I am using this technique to avoid the from freezing when i start the application because i have a very long process consumes 2 mins, the form in this duration freezes and stop me to do anything, if you can help me to give another technique i will appreciate .
Thanx alot .
|
|
|
|
|
Ramez Quneibi wrote: I am using this technique to avoid the from freezing when i start the application because i have a very long process consumes 2 mins
Don't use a 2nd thread to start the form. If the form itself is doing lots of work, have the form use a background thread to perform the work, thus keeping the UI thread free. You should never do any large amount of work on the UI thread. If you are, most likely you have designed your application incorrectly.
I recommend launching form2 from form1 using the same thread that's running form1. If form2 is doing lots of work, make form2 start a background thread to do the work.
|
|
|
|
|
what do you mean by background thread ? i put the process inside the button click event in a thread.
<br />
private void button9_Click(object sender, System.EventArgs e)<br />
{<br />
new Thread(new ThreadStart(Search)).Start(); <br />
}<br />
private void Search()<br />
{<br />
}<br />
|
|
|
|
|
Ramez Quneibi wrote: what do you mean by background thread ?
I mean a thread other than the UI thread. You did new Thread(new ThreadStart(Search)).Start() ; that just started a background thread. Don't use a background thread to launch Form2. Launch Form2 from the UI thread. If you need to perform search work on a background thread, that's fine, but don't create a UI from you background thread.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Messianic Instrumentals (with audio)
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
ok, this works well, thanx alot
|
|
|
|
|
Is it possible to make an exact copy of an instance of an object (not its reference)?
This is what I'd like to achieve:
1 make a copy of an instance at a certain moment to save the state it's in
2 modify the original for a bit
3 replace the original object with the saved one later on
This way I'd like to be able to "recall" the state my object was in at the moment I made a copy. Is this possible without manually constructing a new object of this type and copying all of it's members?
|
|
|
|
|
To do this, you can binary serialize the object. Serialize the object to a memory stream and then deserialize to a new instance. For classes that don't have a CopyTo method, this is pretty helpful. However, the class that you're serializing has to have the Serializable attribute.
Logifusion[^]
If not entertaining, write your Congressman.
|
|
|
|
|
Actually it is Serializable since it can be stored to disk too. I just had a go with this but I haven't serialized to memory before and for some reason I'm getting a
System.Runtime.Serialization.SerializationException: End of Stream encountered before parsing was completed.<br />
The code looks like this.
Collection<MyOutput> myOutputCollection = new Collection<MyOutput>();
BinaryFormatter bFormatter = new BinaryFormatter();
MemoryStream mStream = new MemoryStream();
OutputData myOutput;
bFormatter.Serialize(mStream, myOutput);
deserializedOutput = (OutputData)bFormatter.Deserialize(mStream);
myOutputCollection.add(deserializedOutput);
mStream.Close();
I'm serializing and deserializing the object, then adding it to a collection, since I'm still using it from the collection once it's added (it's not like I don't need it anymore).
|
|
|
|
|
Before you deserialize, you have to rewind the memory stream back to the initial position.
Logifusion[^]
If not entertaining, write your Congressman.
|
|
|
|
|
This works, thx
|
|
|
|
|
In short you want something to that gives you an 'undo' feature. I don't like recommending 'design patterns' without looking at several alternatives, but in this case the Memento pattern fits well.
Googling will give you a solid explanation.
Wikipedia has a short code sample:
Memento pattern[^]
|
|
|
|
|
I see the use of the pattern, but it seems this will only work for a single member that defines the state, while I meant the state of the object itself and all of its members... I'm afraid this won't work, but thanks for the info.
|
|
|
|
|
You could do the following:
Make the following changes to your class:
public class MyClass : ICloneable
{
public MyClass(){}
public MyClass(object newInstance)
{
if ( !(newInstance is MyClass) ) throw new Exception...
MyClass instance = (MyClass)newInstance;
}
public object Clone
{
return (object)this;
{
}
Then in your code you would do as follows:
...
MyClass newObject = new MyClass(oldObject.Clone());
Unfortunately, there is no ICloneable<t> and object is all you can pass.
|
|
|
|
|
Wesner Moise has a good blog posting[^] regarding how to clone objects that don't implement ICloneable. He basically uses reflection to invoke the protected MemberwiseClone method.
If you have the source code to this object, I'd just make it implement ICloneable.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Messianic Instrumentals (with audio)
The apostle Paul, modernly speaking: Epistles of Paul
Judah Himango
|
|
|
|
|
Looks interesting, I'll try this out...
|
|
|
|
|
Works perfectly... Thank you.
|
|
|
|
|
I'm doing this using the Clone method of the object. I think there's no universal mechanism for copying objects, so you need to implement this method by your own. If you are working with more types, it is good to use some ICloneable interface.
This is an example:
<br />
public interface ICloneable {<br />
<br />
object Clone();<br />
}<br />
<br />
public class BitmapWithArray : ICloneable {<br />
<br />
public Bitmap bitmap = null;<br />
public int[] array = null;<br />
public ushort someValue = 0;<br />
<br />
public object Clone() {<br />
<br />
BitmapWithArray obj = new BitmapWithArray();<br />
<br />
if (this.bitmap != null)<br />
obj.bitmap = (Bitmap)this.bitmap.Clone();<br />
<br />
if (this.array != null)<br />
obj.array = (int[])this.array.Clone();<br />
<br />
obj.someValue = this.someValue;
}<br />
}<br />
|
|
|
|