Share via


使用 AsyncCallback 委派和狀態物件

可等待非同步作業結果,並同時執行其他工作的應用程式,不應該在作業完成之前封鎖等待。 請使用下列其中一個選項,在等待非同步作業完成時,繼續執行指令:

  • 請使用 AsyncCallback 委派,處理個別執行緒中非同步作業的結果。 此主題中會示範這個方法。

  • 請使用非同步作業的 BeginOperationName 方法所傳回之 IAsyncResultIsCompleted 屬性,判斷作業是否已完成。 如需進行這個方法的範例,請參閱輪詢非同步作業的狀態

範例

下列程式碼範例會示範使用 Dns 類別中的非同步方法,以擷取使用者指定之電腦的網域名稱系統 (DNS) 資訊。 這個範例會定義並使用 HostRequest 類別以儲存狀態資訊。 使用者輸入的每個電腦名稱都會建立 HostRequest 物件。 這個物件會傳遞至 BeginGetHostByName 方法。 每次有要求完成時,都會呼叫 ProcessDnsInformation 方法。 HostRequest 物件是使用 AsyncState 屬性來擷取的。 ProcessDnsInformation 方法會使用 HostRequest 物件來儲存要求所傳回的 IPHostEntry,或要求所擲回的 SocketException。 當所有的要求都完成之後,應用程式會逐一查看 HostRequest 物件,並顯示 DNS 資訊或 SocketException 錯誤訊息。

' The following example demonstrates using asynchronous methods to
' get Domain Name System information for the specified host computer.

Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Collections

Namespace Examples.AdvancedProgramming.AsynchronousOperations
' Create a state object that holds each requested host name, 
' an associated IPHostEntry object or a SocketException.
    Public Class HostRequest
        ' Stores the requested host name.
        Dim hostNameValue as string
        ' Stores any SocketException returned by the Dns EndGetHostByName method.
        Dim e as SocketException
        ' Stores an IPHostEntry returned by the Dns EndGetHostByName method.
        Dim entry as IPHostEntry

        Public Sub New(name as String)
            hostNameValue = name
        End Sub

        ReadOnly Public Property HostName as String
            Get
                return hostNameValue
            End Get
        End Property

        Public Property ExceptionObject as SocketException
            Get
                return e
            End Get
            Set
                 e = value
            End Set
        End Property

        Public Property HostEntry as IPHostEntry
            Get
                return entry
            End Get
            Set
                entry = value
            End Set
        End Property
    End Class

    Public Class UseDelegateAndStateForAsyncCallback
        ' The number of pending requests.
        Dim Shared requestCounter as Integer
        Dim Shared hostData as ArrayList = new ArrayList()

        Shared Sub UpdateUserInterface()
            ' Print a message to indicate that the application
            ' is still working on the remaining requests.
            Console.WriteLine("{0} requests remaining.", requestCounter)
        End Sub

        Public Shared Sub Main()
            ' Create the delegate that will process the results of the 
            ' asynchronous request.
            Dim callBack as AsyncCallback = AddressOf ProcessDnsInformation
            Dim host as string

            Do
                Console.Write(" Enter the name of a host computer or <enter> to finish: ")
                host = Console.ReadLine()
                If host.Length > 0
                    ' Increment the request counter in a thread safe manner.
                    Interlocked.Increment (requestCounter)
                    ' Create and store the state object for this request.
                    Dim  request as HostRequest = new HostRequest(host)
                    hostData.Add(request)
                    ' Start the asynchronous request for DNS information.
                    Dns.BeginGetHostEntry(host, callBack, request)
                 End If
            Loop While host.Length > 0

            ' The user has entered all of the host names for lookup.
            ' Now wait until the threads complete.
            Do While requestCounter > 0
                UpdateUserInterface()
            Loop

            ' Display the results.
            For Each r as HostRequest In hostData
                    If IsNothing(r.ExceptionObject) = False
                        Console.WriteLine( _ 
                          "Request for host {0} returned the following error: {1}.", _
                          r.HostName, r.ExceptionObject.Message)
                    Else
                        ' Get the results.
                        Dim h as IPHostEntry = r.HostEntry
                        Dim aliases() as String = h.Aliases
                        Dim addresses() as IPAddress = h.AddressList
                        Dim j, k as Integer

                        If aliases.Length > 0
                            Console.WriteLine("Aliases for {0}", r.HostName)
                            For j = 0 To aliases.Length - 1
                                Console.WriteLine("{0}", aliases(j))
                            Next j
                        End If
                        If addresses.Length > 0
                            Console.WriteLine("Addresses for {0}", r.HostName)
                            For k = 0 To addresses.Length -1
                                Console.WriteLine("{0}",addresses(k).ToString())
                            Next k
                        End If
                    End If
            Next r
       End Sub

        ' The following method is invoked when each asynchronous operation completes.
        Shared Sub ProcessDnsInformation(result as IAsyncResult)
           ' Get the state object associated with this request.
           Dim request as HostRequest= CType(result.AsyncState,HostRequest)
            Try 
                ' Get the results and store them in the state object.
                Dim host as IPHostEntry = Dns.EndGetHostEntry(result)
                request.HostEntry = host
            Catch e as SocketException
                ' Store any SocketExceptions.
                request.ExceptionObject = e
            Finally 
                ' Decrement the request counter in a thread-safe manner.
                Interlocked.Decrement(requestCounter)
            End Try
        End Sub
    End Class
End Namespace
/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computer.
*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
// Create a state object that holds each requested host name, 
// an associated IPHostEntry object or a SocketException.
    public class HostRequest
    {
        // Stores the requested host name.
        private string hostName;
        // Stores any SocketException returned by the Dns EndGetHostByName method.
        private SocketException e;
        // Stores an IPHostEntry returned by the Dns EndGetHostByName method.
        private IPHostEntry entry;

        public HostRequest(string name)
        {
            hostName = name;
        }

        public string HostName
        {
            get 
            {
                return hostName;
            }
        }

        public SocketException ExceptionObject
        {
            get 
            {
                return e;
            }
            set 
            {
                 e = value;
            }
        }

        public IPHostEntry HostEntry
        {
            get 
            {
                return entry;
            }
            set 
            {
                entry = value;
            }
        }
    }

    public class UseDelegateAndStateForAsyncCallback
    {
        // The number of pending requests.
        static int requestCounter;
        static ArrayList hostData = new ArrayList();
        static void UpdateUserInterface()
        {
            // Print a message to indicate that the application
            // is still working on the remaining requests.
            Console.WriteLine("{0} requests remaining.", requestCounter);
        }
        public static void Main()
        {
            // Create the delegate that will process the results of the 
            // asynchronous request.
            AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);
            string host;
            do
            {
                Console.Write(" Enter the name of a host computer or <enter> to finish: ");
                host = Console.ReadLine();
                if (host.Length > 0)
                {
                    // Increment the request counter in a thread safe manner.
                    Interlocked.Increment(ref requestCounter);
                    // Create and store the state object for this request.
                    HostRequest request = new HostRequest(host);
                    hostData.Add(request);
                    // Start the asynchronous request for DNS information.
                    Dns.BeginGetHostEntry(host, callBack, request);
                 }
            } while (host.Length > 0);
            // The user has entered all of the host names for lookup.
            // Now wait until the threads complete.
            while (requestCounter > 0)
            {
                UpdateUserInterface();
            }
            // Display the results.
            foreach(HostRequest r in hostData)
            {
                    if (r.ExceptionObject != null)
                    {
                        Console.WriteLine("Request for host {0} returned the following error: {1}.", 
                            r.HostName, r.ExceptionObject.Message);
                    }
                    else
                    {
                        // Get the results.
                        IPHostEntry h = r.HostEntry;
                        string[] aliases = h.Aliases;
                        IPAddress[] addresses = h.AddressList;
                        if (aliases.Length > 0)
                        {
                            Console.WriteLine("Aliases for {0}", r.HostName);
                            for (int j = 0; j < aliases.Length; j++)
                            {
                                Console.WriteLine("{0}", aliases[j]);
                            }
                        }
                        if (addresses.Length > 0)
                        {
                            Console.WriteLine("Addresses for {0}", r.HostName);
                            for (int k = 0; k < addresses.Length; k++)
                            {
                                Console.WriteLine("{0}",addresses[k].ToString());
                            }
                        }
                    }
            }
       }

        // The following method is invoked when each asynchronous operation completes.
        static void ProcessDnsInformation(IAsyncResult result)
        {
           // Get the state object associated with this request.
           HostRequest request = (HostRequest) result.AsyncState;
            try 
            {
                // Get the results and store them in the state object.
                IPHostEntry host = Dns.EndGetHostEntry(result);
                request.HostEntry = host;
            }
            catch (SocketException e)
            {
                // Store any SocketExceptions.
                request.ExceptionObject = e;
            }
            finally 
            {
                // Decrement the request counter in a thread-safe manner.
                Interlocked.Decrement(ref requestCounter);
            }
        }
    }
}

請參閱

概念

事件架構非同步模式概觀

使用 AsyncCallback 委派結束非同步作業

其他資源

非同步程式設計模式