我想调用一个返回IAsyncResult
对象的异步操作,特别是GetHostEntry
类的System.Net.Dns
方法。
我理解我应该调用WaitOne
AsyncWaitHandle
IAsyncResult
属性的using System;
using System.Net;
static class Program {
class GetHostEntryState {
public IPHostEntry Value {
get;
set;
}
}
static void Main(string[] args) {
string hostName = "somehost";
int timeout = 1000;
var state = new GetHostEntryState();
var asyncResult = Dns.BeginGetHostEntry(hostName, ar => {
((GetHostEntryState)ar.AsyncState).Value = Dns.EndGetHostEntry(ar);
}, state);
if (asyncResult.AsyncWaitHandle.WaitOne(timeout) && asyncResult.IsCompleted) {
if (state.Value == null) {
// we always hit this condition
Console.WriteLine("state.Value == null");
return;
}
foreach (var address in state.Value.AddressList) {
Console.WriteLine(address);
}
} else {
Console.WriteLine("timed out");
}
}
}
方法等待一定的超时时间才能完成操作,但显然我是错了,因为这段代码不起作用:
ManualResetEvent
example in msdn使用AsyncWaitHandle
对象进行同步。这有必要吗?如果是,那么{{1}}属性的用途是什么?
答案 0 :(得分:1)
由于我想要的是具有超时的GetHostEntry,我想出了这个解决方案,如果我理解正确的话,应该避免泄漏资源,因为最终将调用EndGetHostEntry操作。
我在这里分享以防它对其他人有用:)
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public sealed class HostEntryTimeout {
public IPHostEntry HostEntry {
get;
private set;
}
string _hostName;
int _timeoutInMilliseconds;
ManualResetEvent _getHostEntryFinished;
public HostEntryTimeout(string alias, int timeoutInMilliseconds) {
_hostName = alias;
_timeoutInMilliseconds = timeoutInMilliseconds;
_getHostEntryFinished = new ManualResetEvent(false);
}
/// <summary>
/// Gets the IPHostEntry.
/// </summary>
/// <returns>True if successful, false otherwise.</returns>
public bool GetHostEntry() {
_getHostEntryFinished.Reset();
Dns.BeginGetHostEntry(_hostName, GetHostEntryCallback, null);
if (!_getHostEntryFinished.WaitOne(_timeoutInMilliseconds)) {
return false;
}
if (HostEntry == null) {
return false;
}
return true;
}
void GetHostEntryCallback(IAsyncResult asyncResult) {
try {
HostEntry = Dns.EndGetHostEntry(asyncResult);
} catch (SocketException) {
}
_getHostEntryFinished.Set();
}
}
然后就可以这样使用:
var hostEntryTimeout = new HostEntryTimeout("somehost", 1000);
if (hostEntryTimeout.GetHostEntry()) {
// success, do something with the hostEntryTimeout.HostEntry object
}