原來的答案
看看更新的答案
沒有實際上取消Dns.BeginGetHostEntry()
但你可以嘗試實現的東西,可以在設定的時間後,被取消的方式。這有些黑客,但可以按照你的要求去做。
但是,DNS查找(通常)非常快,測試通常在10ms內解析。
下面是一個示例。基本上使基於Task
的方法,允許您執行一個Task
返回一個布爾結果是否完成。當執行解析它創建了一個內部AsyncCallBack
代表
public static Task<bool> Resolve(string hostNameOrAddress, int millisecond_time_out)
{
return Task.Run(async() =>
{
bool completed = false;
var asCallBack = new AsyncCallback(ar =>
{
ResolveState context = (ResolveState)ar.AsyncState;
if (context.Result == ResolveType.Pending)
{
try
{
var ipList = Dns.EndGetHostEntry(ar);
if (ipList == null || ipList.AddressList == null || ipList.AddressList.Length == 0)
context.Result = ResolveType.InvalidHost;
else
context.Result = ResolveType.Completed;
}
catch
{
context.Result = ResolveType.InvalidHost;
}
}
completed = true;
});
ResolveState ioContext = new ResolveState(hostNameOrAddress);
var result = Dns.BeginGetHostEntry(ioContext.HostName, asCallBack, ioContext);
int miliCount = 0;
while (!completed)
{
miliCount++;
if (miliCount >= millisecond_time_out)
{
result.AsyncWaitHandle.Close();
result = null;
ioContext.Result = ResolveType.Timeout;
break;
}
await Task.Delay(1);
}
Console.WriteLine($"The result of {ioContext.HostName} is {ioContext.Result}");
return ioContext.Result == ResolveType.Completed;
});
}
public class ResolveState
{
public ResolveState(string hostName)
{
if (string.IsNullOrWhiteSpace(hostName))
throw new ArgumentNullException(nameof(hostName));
_hostName = hostName;
}
readonly string _hostName;
public ResolveType Result { get; set; } = ResolveType.Pending;
public string HostName => _hostName;
}
public enum ResolveType
{
Pending,
Completed,
InvalidHost,
Timeout
}
的方法,然後可以稱爲
public static async void RunTest()
{
await Resolve("asdfasdfasdfasdfasdfa.ca", 60);
await Resolve("google.com", 60);
}
。然後將該代表傳遞給Dns.BeginGetHostEntry()
方法。另外我們還通過了state
對象ResolveState
。此狀態對象可用於管理上下文之間的狀態。因此,當AsyncCallBack
得到執行時,我們可以設置ResolveState
的Result
。接下來,completed
標誌被設置爲指示回調委託完成。
最後(這是我不喜歡的部分),然後我們有一個循環,每執行和1ms
如果超時設置我們的狀態對象的Result
到Timeout
。
這又有點駭人聽聞,但確實導致了所需的效果。現在這也是async
,所以你可以使用功能async
& await
功能。
更新回答
我不喜歡的結果,並審查了最初的問題的第一個答案之後。除了我們需要檢查完整的標誌之外,你們走在了正確的軌道上。但如果result
在WaitOne
調用後未完成,則success
將返回false。如果完成,那麼success
將是true
(即使沒有解析IP地址),然後您需要使用Dns.EndGetHostEntry
檢查結果。
修改後的代碼:
public static bool ResolveTest(string hostNameOrAddress, int millisecond_time_out)
{
ResolveState ioContext = new ResolveState(hostNameOrAddress);
var result = Dns.BeginGetHostEntry(ioContext.HostName, null, null);
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(millisecond_time_out), true);
if (!success)
{
ioContext.Result = ResolveType.Timeout;
}
else
{
try
{
var ipList = Dns.EndGetHostEntry(result);
if (ipList == null || ipList.AddressList == null || ipList.AddressList.Length == 0)
ioContext.Result = ResolveType.InvalidHost;
else
ioContext.Result = ResolveType.Completed;
}
catch
{
ioContext.Result = ResolveType.InvalidHost;
}
}
Console.WriteLine($"The result of ResolveTest for {ioContext.HostName} is {ioContext.Result}");
return ioContext.Result == ResolveType.Completed;
}
下面是完整的要點https://gist.github.com/Nico-VanHaaster/35342c1386de752674d0c37ceaa65e00。
答案已更新,更好看的版本 – Nico