|
||
|
|
#1 (permalink) |
|
Forum Expert
|
Working on my RunUO Remote GUI thing...
So, basically, I'm doing async socket operations. When I push a connect button on my form, I start by doing an async Dns.GetHostEntry to resolve the address of the server. When it completes, I begin an async connect. Code: Code:
#region Connecting and DNS
private void GetHostEntryCallback(IAsyncResult ar)
{
try
{
IPHostEntry e = Dns.EndGetHostEntry(ar);
if (e.AddressList.Length == 0)
throw new Exception("No address associated with hostname.");
m_Server.Address = e.AddressList[0];
BeginInternalConnect();
}
catch (Exception e)
{
QueueMessage(String.Format("[!] Resolve failed: {0}", e.Message));
}
}
public void BeginConnect()
{
IPAddress addr = null;
try
{
addr = IPAddress.Parse(m_Server.ServerHostName);
}
catch
{
addr = null;
}
if (addr == null)
{
QueueMessage(String.Format("[+] Resolving {0}...", m_Server.ServerHostName));
Dns.BeginGetHostEntry(m_Server.ServerHostName, new AsyncCallback(GetHostEntryCallback), null);
}
else
{
m_Server.Address = addr;
BeginInternalConnect();
}
}
public void BeginInternalConnect()
{
QueueMessage(String.Format("[+] Connecting to {0}...", m_Server.Address.ToString()));
IPEndPoint hostPoint = new IPEndPoint(m_Server.Address, m_Server.ServerPort);
try
{
m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_Socket.BeginConnect(hostPoint, new AsyncCallback(ConnectCallback), null);
}
catch (Exception e)
{
QueueMessage(String.Format("[!] Can't connect: {0}", e.Message));
m_Socket.Close();
m_Socket = null;
}
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
m_Socket.EndConnect(ar);
m_Connected = true;
QueueMessage(String.Format("[+] Connected to {0} ({1})", m_Server.ServerHostName, m_Server.Address));
m_Server.ConnectedAt = DateTime.Now;
}
catch (SocketException e)
{
m_Socket.Close();
m_Socket = null;
QueueMessage(String.Format("[!] Can't connect: {0}", e.Message));
}
catch
{
m_Socket.Close();
m_Socket = null;
QueueMessage("[!] Unknown error. Can't connect!");
}
}
#endregion
Now, the problem is, sometimes I get this really annoying SocketException, goes like "The attempted operation is not supported for the type of object referenced." The description from MSDN goes: "Operation not supported. The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation is trying to accept a connection on a datagram socket." It doesn't make a lot of sense. I'm not using a datagram socket, obviously. When I push connect the first time, I always get that exception thrown from BeginConnect, but if I push it again right after that, it works. Getting it out of other WinSock functions too, like Disconnect. Really puzzling. So, am I just stupid? Something I'm not doing right? I've tried it every different way I could think of. First I tried changing the way I use BeginConnect, by using a string to let it resolve itself, same thing. I tried a IPAddress instead of IPEndPoint. Same thing. I thought maybe calling the BeginInternalConnect from the DNS callback might be a problem, so I tried having my worker thread do the call to BeginInternalConnect when the DNS was finished. Same thing. Tried making ConnectCallback static and passing a reference to the object via AsyncResult, so I can access data from the instance. Same thing. Any advise or insight would be greatly appreciate!
__________________
|
|
|
|
|
|
#2 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
do not call another async method within an async method or delegate. AFAIK, it is a bug with .NET 2.0 about thread pooling mechanism.
you might remove second async callback method let me know whether it works or not..
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#3 (permalink) |
|
Master of the Internet
Join Date: Oct 2005
Age: 44
Posts: 6,283
|
Is there an IPv6 address involved anywhere?
__________________
Why is it that I'm never as smart as I thought I was yesterday? My vast knowledge is only surpassed by my infinite ignorance. <TheOutkastDev> i might have to hire an assassin to killl mal so that i can jump in front of the bullet and piss on him |
|
|
|
|
|
#4 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
by the way, earlier I said it is a bug but it might also be considered as a design issue.
here is the problem about the code: when you call an async method, the process is handled by a worker thread from thread pool. as soon as the process is completed, the worker thread returns to pool and callback method is invoked in the "caller thread" so if you invoke another async method/delegete within an async method/delegate, here is what happens sometimes: if the first async method is completed and the worker thread returned to thread pool already when the inner (second) async method is finished, it tries to get first worker thread (for callback method). but by the time then, it might be used for another process since it is a thread pool.
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#5 (permalink) | |
|
Forum Expert
|
Quote:
I should also note, when I coded it to use the BeginConnect overload that takes a string and does a resolve on it's own, thereby eliminating my async Dns query, the problem is still present. Just not sure how to go about fixing it. :P
__________________
|
|
|
|
|
|
|
#6 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
just use Socket#Connect instead of Socket#BeginConnect.
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#7 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
I want to correct a few things:
callbacks are processed by the same worker thread. however after it is done, it tries to invoke a Completed event in the caller thread which is the problem. btw, this article might be useful for you since you are writing a GUI appl. CoDe Magazine - Article: Asynchronous Windows Forms Programming
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
|
|
#8 (permalink) |
|
Forum Expert
|
Not an option. I don't want my program blocked while the tcp/ip stack is doing stuff, like resolving, or connecting. That's just annoying.
The article is definitely interesting, but it applies to .NET 1.1, and I'm working with 2.0, and these methods are new to 2.0. At any rate, thanks for yer help. I'll get it figured out. At worst, it's annoying, at best, it doesn't happen. Not pouring much more time into it, right now. I can get it to connect, want to start getting the real meat of my app coded and functioning. ![]()
__________________
|
|
|
|
|
|
#9 (permalink) |
|
Forum Expert
Join Date: Nov 2003
Location: Illinois, USA
Age: 21
Posts: 2,909
|
well if you dont want it to be blocked, you can always create your own threads to do some of this stuff, then you would only destroy the thread once all of the async stuff is finished (that way you arent using async methods inside of other async methods)
__________________
Useful links (Use them or die in a fire!!!): Ultimate Little Guide, C# Tutorials & Docs, RunUO Basic Scripts, Run UO How to..., Configure server for connections, Scripting for Dummies, Common Problem Solutions, FAQ Forum, RunUO Wiki, Basic Generics, Xml Tutorial |
|
|
|
|
|
#10 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
it shouldnt be blocked when you use Connect instead of BeginConnect.
in UI thread, you already call an async delegate, which will not block UI thread untill its callback method is done. why do you need to use async method for Connect? It doesnt matter whether your thread (its a worker thread in this case, not UI thread, be careful) is blocked or not. and given your code, your worker thread doesnt do anything after calling BeginConnect, so there is no need to be using async method there.
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." Last edited by noobie; 02-18-2007 at 02:57 AM. |
|
|
|
|
|
#11 (permalink) | |
|
Forum Expert
|
Quote:
mordero there has a good idea though, use my own threading to do such things. I may just go about doing that, that would simplify everything since I'd know exactly what's going on. Thanks mordero. ![]()
__________________
Last edited by Cheetah2003; 02-18-2007 at 03:46 AM. |
|
|
|
|
|
|
#12 (permalink) |
|
Forum Expert
Join Date: Jul 2005
Location: Istanbul/Turkey
Age: 27
Posts: 425
|
OK, I think I didnt make it clear.
Connect part will be executed in a worker thread which is created by async delegate. So it shouldnt block your UI thread whether it waits one or ten seconds. to see exactly what happens in your code. Write a debug statements like this in the beginning of each method: QueueMessage("<MethodName> "+Thread.GetCurrentThread().IsThreadPoolThread +" "+Thread.GetCurrentThread().GetHashCode());
__________________
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|