Reputation: 4204
I am trying to asynchronously resolve an IP address to host name using C# and then add the result to a ListBox. The asynchronous operation works alright but i can not add the resolved name to a listbox because another thread owns it. How can i bypass this issue and add the resolved name to a listbox.
here is what i've done so far
public static ManualResetEvent GetHostEntryFinished = new ManualResetEvent(false);
private void AsyncDNSResolver(string IPString)
{
GetHostEntryFinished.Reset();
IPHostEntry host = new IPHostEntry();
host.AddressList = new IPAddress[] { IPAddress.Parse(IPString) };
Dns.BeginGetHostEntry(host.AddressList[0], new AsyncCallback(GetHostEntryCallback), host);
GetHostEntryFinished.WaitOne();
}
public static void GetHostEntryCallback(IAsyncResult ar)
{
IPHostEntry host = (IPHostEntry)ar.AsyncState;
while (!ar.IsCompleted) ;
host = Dns.EndGetHostEntry(ar);
lsvHosts.items.add(host.HostName);
GetHostEntryFinished.Set();
}
Upvotes: 0
Views: 1695
Reputation: 16812
If you wanted to execute an expensive activity on a separate thread and continue working while waiting for the result you can use this code snippet.
static void Main(string[] args)
{
Console.WriteLine("About to call DNS");
ResolveDnsAndPerformWorkWhileWaiting("74.125.237.112");
Console.Read();
}
public static void ResolveDnsAndPerformWorkWhileWaiting(string ipaddress)
{
var task = new Task<string>(() =>
{
var host = new IPHostEntry { AddressList = new[] { IPAddress.Parse(ipaddress) } };
var result = Dns.GetHostEntry(host.AddressList[0]);
return result.HostName;
});
// execute the work on another thread
task.Start();
// do other stuff
// use the results (if the task has not finished the .Result property will hold until completed)
var resolvedAddress = task.Result;
Console.WriteLine("Resolved address:" + resolvedAddress);
}
If you are using a Windows Forms application then the easiest way would be to use a BackgroundWorker
, here is a code sample
static void Main(string[] args)
{
Console.WriteLine("About to call DNS");
var worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync("74.125.237.112");
Console.Read();
}
static void worker_DoWork(object sender, DoWorkEventArgs e)
{
var host = new IPHostEntry { AddressList = new[] { IPAddress.Parse((string)e.Argument) } };
var result = Dns.GetHostEntry(host.AddressList[0]);
e.Result = result.HostName;
}
static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// You could set your UI control here like label1.text = (string)e.Result
Console.WriteLine((string)e.Result);
}
Upvotes: 1
Reputation: 84784
The intention is that you would continue execution from GetHostEntryCallback
(which could be anonymous within AsyncDNSResolver
) and raise another event to return the data to the caller. This the nature of the asynchronous programming model available to you (pre-C# 5). In this case, AsyncDNSResolver
cannot return string
because it won't be available by the time it exits.
Your choice comes down to:
AsyncDNSResolver
Dns.GetHostEntry
instead.Upvotes: 1