Ten artykuł został przetłumaczony przez maszynę. Aby wyświetlić jego treść w języku angielskim, zaznacz pole wyboru Angielski. Możesz też wyświetlić angielski tekst w okienku wyskakującym, przesuwając wskaźnik myszy nad konkretny tekst”.
Tłumaczenie
Angielski

Wywołanie metod synchronicznych w sposób asynchroniczny

.NET Framework (current version)
 

.NET Framework umożliwia asynchroniczne wywoływanie dowolnej metody. W tym celu zdefiniowania delegat o tym samym podpisie metody, które chcesz wywołać; środowisko uruchomieniowe języka wspólnego automatycznie definiuje BeginInvoke i EndInvoke metody ten delegat z odpowiednim podpisem.

System_CAPS_noteUwaga

Wywołuje asynchroniczne delegata, w szczególności BeginInvoke i EndInvoke metody, nie są obsługiwane w programie .NET Compact Framework.

BeginInvoke Metoda Inicjuje asynchroniczne wywołanie. Ma te same parametry jako metodę, która ma być wykonana asynchronicznie, a także dwa dodatkowe parametry opcjonalne. Pierwszy parametr jest AsyncCallback delegata, który odwołuje się do metody do wywołania po zakończeniu asynchroniczne wywołanie. Drugi parametr jest obiektem zdefiniowane przez użytkownika, który przekazuje informacje do metody wywołania zwrotnego. BeginInvoke Zwraca natychmiast, a nie oczekuje asynchroniczne wywołanie do ukończenia. BeginInvoke Zwraca IAsyncResult, który może służyć do monitorowania postępu wywołania asynchronicznego.

EndInvoke Metoda pobiera wyników wywołania asynchronicznego. Może ona zostać wywołana dowolnej chwili po BeginInvoke. Jeśli asynchroniczne wywołanie nie zostało ukończone, EndInvoke blokuje wątek wywołujący, dopóki nie zakończy on. Parametry EndInvoke obejmują out i ref Parametry (< Out > ByRef i ByRef w języku Visual Basic) metody, która ma być wykonana asynchronicznie, wraz z IAsyncResult zwrócone przez BeginInvoke

System_CAPS_noteUwaga

Funkcja IntelliSense w Visual Studio 2005 Wyświetla parametry BeginInvoke i EndInvoke. Jeśli nie używasz programu Visual Studio lub podobnego narzędzia lub jeśli używasz C# i Visual Studio 2005, zobacz Model programowania asynchronicznego (APM) Opis parametrów zdefiniowanych dla tych metod.

Przykłady kodu, w tym temacie ilustrują cztery typowe sposoby użycia BeginInvoke i EndInvoke do wywołania asynchronicznego. Po wywołaniu BeginInvoke można wykonać następujące czynności:

  • Czy niektóre pracy, jak i wywoływać EndInvoke do bloku do momentu ukończenia wywołania.

  • Uzyskaj WaitHandle przy użyciu IAsyncResult.AsyncWaitHandle Właściwości, należy zastosować jego WaitOne metody wykonywania bloku do WaitHandle jest sygnalizuje, a następnie wywołać EndInvoke.

  • Sondowania IAsyncResult zwrócone przez BeginInvoke do określenia po ukończeniu wywołania asynchroniczne, a następnie wywołać EndInvoke.

  • Przekazywanie delegata dla metody wywołania zwrotnego BeginInvoke. Metoda jest wykonywana na ThreadPool wątków po zakończeniu wywołania asynchronicznego. Wywołania metody wywołania zwrotnego EndInvoke.

System_CAPS_importantWażne

Niezależnie od techniki, należy wywołać zawsze EndInvoke do uzyskania połączenia asynchronicznego.

Przykłady kodu, które podlegają pokazują różne sposoby wywołanie tej samej metody długotrwała TestMethod, asynchronicznie. TestMethod Metoda wyświetla komunikat konsoli, aby pokazać rozpoczął przetwarzanie sen przez kilka sekund, a następnie kończy. TestMethod ma out parametr przedstawiają sposób takie parametry są dodawane do podpisy BeginInvoke i EndInvoke. Można obsługiwać ref Parametry podobnie.

Poniższy przykładowy kod przedstawia definicję TestMethod i delegat o nazwie AsyncMethodCaller można wywołać TestMethod asynchronicznie. Aby skompilować przykłady kodu, musi zawierać definicje TestMethod i AsyncMethodCaller delegować.

using System;
using System.Threading; 

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncDemo 
    {
        // The method to be executed asynchronously.
        public string TestMethod(int callDuration, out int threadId) 
        {
            Console.WriteLine("Test method begins.");
            Thread.Sleep(callDuration);
            threadId = Thread.CurrentThread.ManagedThreadId;
            return String.Format("My call time was {0}.", callDuration.ToString());
        }
    }
    // The delegate must have the same signature as the method
    // it will call asynchronously.
    public delegate string AsyncMethodCaller(int callDuration, out int threadId);
}

Najprostszym sposobem asynchroniczne wykonywanie metody jest rozpoczęcie wykonywania metody przez wywołanie delegata BeginInvoke metody, niektóre pracy w głównym wątku, a następnie wywołać delegata EndInvoke metody. EndInvoke mogą zablokować wątek wywołujący, ponieważ nie zwraca do momentu ukończenia wywołania asynchronicznego. Jest to dobra metoda do użycia z pliku lub sieci operacji.

System_CAPS_importantWażne

Ponieważ EndInvoke może spowodować zablokowanie, nigdy nie należy wywołać go z wątków, które Usługa interfejsu użytkownika.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        public static void Main() 
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // Call EndInvoke to wait for the asynchronous call to complete,
            // and to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */

Można uzyskać WaitHandle za pomocą AsyncWaitHandle Właściwość IAsyncResult zwrócone przez BeginInvoke. WaitHandle To zasygnalizować po zakończeniu wywołania asynchroniczne, a można poczekać na jego przez wywołanie WaitOne metody.

Jeśli używasz WaitHandle, można wykonać dodatkowe przetwarzanie przed lub po zakończeniu asynchroniczne wywołanie, ale przed wywołaniem funkcji EndInvoke do pobierania wyników.

System_CAPS_noteUwaga

Dojście oczekiwania nie zostaną automatycznie zamknięte podczas wywoływania EndInvoke. Po zwolnieniu wszystkie odwołania do dojście oczekiwania zasoby systemu są zwalniane podczas wyrzucania elementów bezużytecznych odzyskuje dojście oczekiwania. Aby zwolnić zasoby systemowe zaraz po zakończeniu używania dojście oczekiwania, usunięcia ich przez wywołanie metody WaitHandle.Close metody. Wyrzucanie elementów bezużytecznych działa wydajniej, gdy obiekty usuwalne jawnie są usuwane.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() 
        {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            Thread.Sleep(0);
            Console.WriteLine("Main thread {0} does some work.",
                Thread.CurrentThread.ManagedThreadId);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            // Perform additional processing here.
            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
 */

Można użyć IsCompleted Właściwość IAsyncResult zwrócone przez BeginInvoke do odnajdywania po zakończeniu asynchroniczne wywołanie. Może to zrobić podczas wywołania asynchronicznego z wątku który usług interfejsu użytkownika. Sondowanie w celu ukończenia umożliwia wątek wywołujący kontynuować wykonywanie podczas wywołania asynchronicznego wykonuje na ThreadPool wątku.

using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() {
            // The asynchronous method puts the thread id here.
            int threadId;

            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // Initiate the asychronous call.
            IAsyncResult result = caller.BeginInvoke(3000, 
                out threadId, null, null);

            // Poll while simulating work.
            while(result.IsCompleted == false) {
                Thread.Sleep(250);
                Console.Write(".");
            }

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("\nThe call executed on thread {0}, with return value \"{1}\".",
                threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

Test method begins.
.............
The call executed on thread 3, with return value "My call time was 3000.".
 */

Jeśli wątek, który inicjuje asynchroniczne wywołanie musi być wątek, który przetwarza wyniki, można wykonać metody wywołania zwrotnego po zakończeniu wywołania. Metody wywołania zwrotnego jest wykonywany na ThreadPool wątku.

Aby użyć metody wywołania zwrotnego, należy podać BeginInvokeAsyncCallback delegata, który reprezentuje metody wywołania zwrotnego. Można również przekazać obiekt, który zawiera informacje używane przez metodę wywołania zwrotnego. Metody wywołania zwrotnego można rzutować IAsyncResult, który jest tylko parametr metody wywołania zwrotnego do AsyncResult obiektu. Następnie można użyć AsyncResult.AsyncDelegate Właściwość do pobrania delegata, które zostało użyte do inicjowania wywołanie, dzięki czemu można wywołać EndInvoke.

Uwagi dotyczące na przykład:

  • threadId Parametru TestMethod jest out parametr (< Out > ByRef w języku Visual Basic), więc jego wartości wejściowej nigdy nie jest używany przez TestMethod Fikcyjny zmiennej jest przekazywany do BeginInvoke wywołań. Jeśli threadId zostały parametru ref parametr (ByRef w języku Visual Basic), zmienna musi mieć pole poziomie klasy, aby go można przekazać do obu BeginInvoke i EndInvoke.

  • Informacje o stanie, który jest przekazywany do BeginInvoke jest ciąg formatu, który używa metody wywołania zwrotnego do formatowania wiadomości danych wyjściowych. Ponieważ jest przekazywany jako typ Object, informacje o stanie musi być rzutowany jego odpowiedniego typu, zanim będzie można go używać.

  • Wywołanie zwrotne jest podejmowana ThreadPool wątku. ThreadPool wątki są wątki w tle, które nie prowadzą ta aplikacja jest uruchomiona, gdy kończy się wątku głównego, więc nie wątku głównego przykładu w stan uśpienia wystarczająco długo na zakończenie wywołania zwrotnego.

using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain 
    {
        static void Main() 
        {
            // Create an instance of the test class.
            AsyncDemo ad = new AsyncDemo();

            // Create the delegate.
            AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);

            // The threadId parameter of TestMethod is an out parameter, so
            // its input value is never used by TestMethod. Therefore, a dummy
            // variable can be passed to the BeginInvoke call. If the threadId
            // parameter were a ref parameter, it would have to be a class-
            // level field so that it could be passed to both BeginInvoke and 
            // EndInvoke.
            int dummy = 0;

            // Initiate the asynchronous call, passing three seconds (3000 ms)
            // for the callDuration parameter of TestMethod; a dummy variable 
            // for the out parameter (threadId); the callback delegate; and
            // state information that can be retrieved by the callback method.
            // In this case, the state information is a string that can be used
            // to format a console message.
            IAsyncResult result = caller.BeginInvoke(3000,
                out dummy, 
                new AsyncCallback(CallbackMethod),
                "The call executed on thread {0}, with return value \"{1}\".");

            Console.WriteLine("The main thread {0} continues to execute...", 
                Thread.CurrentThread.ManagedThreadId);

            // The callback is made on a ThreadPool thread. ThreadPool threads
            // are background threads, which do not keep the application running
            // if the main thread ends. Comment out the next line to demonstrate
            // this.
            Thread.Sleep(4000);

            Console.WriteLine("The main thread ends.");
        }

        // The callback method must have the same signature as the
        // AsyncCallback delegate.
        static void CallbackMethod(IAsyncResult ar) 
        {
            // Retrieve the delegate.
            AsyncResult result = (AsyncResult) ar;
            AsyncMethodCaller caller = (AsyncMethodCaller) result.AsyncDelegate;

            // Retrieve the format string that was passed as state 
            // information.
            string formatString = (string) ar.AsyncState;

            // Define a variable to receive the value of the out parameter.
            // If the parameter were ref rather than out then it would have to
            // be a class-level field so it could also be passed to BeginInvoke.
            int threadId = 0;

            // Call EndInvoke to retrieve the results.
            string returnValue = caller.EndInvoke(out threadId, ar);

            // Use the format string to format the output message.
            Console.WriteLine(formatString, threadId, returnValue);
        }
    }
}

/* This example produces output similar to the following:

The main thread 1 continues to execute...
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
The main thread ends.
 */
Pokaż: