在BeginXXX和EndXXX方法中使用AsyncWaitHandle

时间:2013-02-05 15:56:38

标签: c# asynchronous dns

我想调用一个返回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}}属性的用途是什么?

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
}