Асинхронное программирование
Summary
With .NET asynchronous programming, a call is made to a .NET class method while the program continues execution, until either the specified callback is made or, if the callback is not provided, until blocking or polling or waiting for the call to complete. For example, a program can call a method, which enumerates a large list, while the main program continues to execute. When the enumeration is complete, a callback is made, and the program addresses it.
Использование асинхронных вызовов
Asynchronous programming is a feature supported by many areas of the .NET Framework, including:
- File IO, Stream IO, Socket IO
- Networking: HTTP, TCP
- Remoting channels (HTTP, TCP) and proxies
- XML Web services created using NET
- NET Web Forms
- Message Queuing using the MessageQueue Class.
- Asynchronous delegates
The .NET Framework allows you to call any method asynchronously. Define a delegate with the same signature as the method you want to call; the common language runtime automatically defines
BeginInvoke and
EndInvoke methods for this delegate, with the appropriate signatures.
This topic demonstrates four common ways to use
BeginInvoke and
EndInvoke to make asynchronous calls. After calling
BeginInvoke you can:
- Do some work and then call EndInvoke to block until the call completes.
- Obtain a WaitHandle? using AsyncWaitHandle?, use its WaitOne? method to block execution until the WaitHandle? is signaled, and then call EndInvoke.
- Poll the IAsyncResult returned by BeginInvoke to determine when the asynchronous call has completed, and then call EndInvoke.
- Pass a delegate for a callback method to BeginInvoke. The method is executed on a ThreadPool thread when the asynchronous call completes, and can call EndInvoke.
CAUTION Always call
EndInvoke after your asynchronous call completes.
Создание асинхронных делегатов
для реализации асинхронного вызова, компилятор C# должен уметь поддерживать асинхронные делегаты. Microsoft C# подерживает эту функциональность. Рассмотрим следующий тестовый пример:
using System;
using System.Threading;
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 = AppDomain.GetCurrentThreadId();
return "MyCallTime was " + callDuration.ToString();
}
}
// The delegate must have the same signature as the method
// you want to call asynchronously.
public delegate string AsyncDelegate(int callDuration, out int threadId);
Асинхронный вызов
See:
BeginInvoke
Ожидание результатов
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());
// Call EndInvoke to Wait for the asynchronous call to complete,
// and to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Ожидание с помощью WaitHandle?
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());
// Wait for the WaitHandle to become signaled.
ar.AsyncWaitHandle.WaitOne();
// Perform additional processing here.
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);
// Poll while simulating work.
while(ar.IsCompleted == false) {
Thread.Sleep(10);
}
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Получение результатов с помощью Callback-функции (AsyncCallback)
public class AsyncMain {
// Asynchronous method puts the thread id here.
private static int threadId;
static void Main(string[] args) {
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
// Initiate the asychronous call. Include an AsyncCallback
// delegate representing the callback method, and the data
// needed to call EndInvoke.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId,
new AsyncCallback(CallbackMethod),
dlgt );
Console.WriteLine("Press Enter to close application.");
Console.ReadLine();
}
// Callback method must have the same signature as the
// AsyncCallback delegate.
static void CallbackMethod(IAsyncResult ar) {
// Retrieve the delegate.
AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".", threadId, ret);
}
}
Ссылки
--
AndreyUstyuzhanin - 06 Apr 2004