以非同步的方式呼叫同步方法
更新: 2008 年 7 月
.NET Framework 讓您可以非同步呼叫任何方法。若要做到這點,請使用與所要呼叫方法相同的簽章 (Signature),來定義一個委派。Common Language Runtime 會自動使用適當的簽章來定義此委派的 BeginInvoke 和 EndInvoke 方法。
注意事項: |
---|
.NET Compact Framework 中不支援非同步委派呼叫,特別是 BeginInvoke 和 EndInvoke 方法。 |
BeginInvoke 方法會啟始非同步呼叫。此方法和您要非同步執行的方法具有相同的參數,再加上兩個額外的選擇性參數。第一個參數是一個 AsyncCallback 委派,會參考在完成非同步呼叫時,所需要呼叫的方法。第二個參數則是使用者定義的物件,會將資訊傳遞至回呼方法。BeginInvoke 會立即傳回,不等待非同步呼叫完成。BeginInvoke 所傳回的 IAsyncResult,可以用來監視非同步呼叫的進度。
EndInvoke 方法則會擷取非同步呼叫的結果。此方法可在 BeginInvoke 之後隨時呼叫。如果非同步呼叫尚未完成,EndInvoke 就會封鎖呼叫執行緒,直到完成為止。EndInvoke 的參數包括您要非同步執行之方法的 out 和 ref 參數 (Visual Basic 中的 <Out>ByRef 和 ByRef),再加上 BeginInvoke 所傳回的 IAsyncResult。
注意事項: |
---|
Visual Studio 2005 中的 IntelliSense 功能會顯示 BeginInvoke 和 EndInvoke 的參數。如果不是使用 Visual Studio 或相似的工具,或者如果是以 Visual Studio 2005 使用 C#,請參閱非同步程式設計概觀中,為這些方法定義的參數描述。 |
此主題中的程式碼會示範使用 BeginInvoke 和 EndInvoke 進行非同步呼叫的四種常見方法。在呼叫 BeginInvoke 之後,您可以進行下列步驟:
進行工作,然後呼叫 EndInvoke 以封鎖直到呼叫完成為止。
使用 IAsyncResult.AsyncWaitHandle 屬性取得 WaitHandle,使用它的 WaitOne 方法來封鎖執行,直到 WaitHandle 收到信號為止,然後再呼叫 EndInvoke。
輪詢 BeginInvoke 所傳回的 IAsyncResult,以判斷非同步呼叫完成的時間,然後呼叫 EndInvoke。
為回呼方法傳遞委派到 BeginInvoke。當非同步呼叫完成時,方法就會在 ThreadPool 執行緒上執行。回呼方法會呼叫 EndInvoke。
重要事項: |
---|
無論使用哪種方式,請永遠呼叫 EndInvoke 來完成您的非同步呼叫。 |
定義測試方法和非同步委派
下列程式碼範例會示範以非同步方式,呼叫相同長時間執行方法 TestMethod 的各種方式。TestMethod 方法會顯示主控台訊息表示已經開始處理、在幾秒鐘的時間內處於睡眠,然後再結束。TestMethod 具有的 out 參數,可以示範對於 BeginInvoke 和 EndInvoke 的簽章,加入這種參數的方式。您也可以用類似的方法來處理 ref。
下列程式碼範例會示範定義 TestMethod,以及可用來非同步呼叫 TestMethod、名為 AsyncMethodCaller 的委派。若要編譯這些程式碼範例,您必須包含 TestMethod 和 AsyncMethodCaller 委派的定義。
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Namespace Examples.AdvancedProgramming.AsynchronousOperations
Public Class AsyncDemo
' The method to be executed asynchronously.
Public Function TestMethod(ByVal callDuration As Integer, _
<Out> ByRef threadId As Integer) As String
Console.WriteLine("Test method begins.")
Thread.Sleep(callDuration)
threadId = Thread.CurrentThread.ManagedThreadId()
return String.Format("My call time was {0}.", callDuration.ToString())
End Function
End Class
' The delegate must have the same signature as the method
' it will call asynchronously.
Public Delegate Function AsyncMethodCaller(ByVal callDuration As Integer, _
<Out> ByRef threadId As Integer) As String
End Namespace
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);
}
using namespace System;
using namespace System::Threading;
using namespace System::Runtime::InteropServices;
namespace Examples {
namespace AdvancedProgramming {
namespace AsynchronousOperations
{
public ref class AsyncDemo
{
public:
// The method to be executed asynchronously.
String^ TestMethod(int callDuration, [OutAttribute] int% threadId)
{
Console::WriteLine("Test method begins.");
Thread::Sleep(callDuration);
threadId = Thread::CurrentThread->ManagedThreadId;
return String::Format("My call time was {0}.", callDuration);
}
};
// The delegate must have the same signature as the method
// it will call asynchronously.
public delegate String^ AsyncMethodCaller(int callDuration, [OutAttribute] int% threadId);
}}}
等待有 EndInvoke 的非同步呼叫
非同步地執行方法的最簡單方式,就是呼叫委派的 BeginInvoke 方法以啟動方法的執行,在主執行緒上進行一些工作,然後呼叫委派的 EndInvoke 方法。由於直到非同步呼叫完成後 EndInvoke 才會傳回,所以此方法可能會封鎖呼叫的執行緒。這是一項能在檔案或網路作業使用的良好技巧。
重要事項: |
---|
由於 EndInvoke 可能會封鎖,所以您不應該從服務使用者介面的執行緒呼叫此方法。 |
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Namespace Examples.AdvancedProgramming.AsynchronousOperations
Public Class AsyncMain
Shared Sub Main()
' The asynchronous method puts the thread id here.
Dim threadId As Integer
' Create an instance of the test class.
Dim ad As New AsyncDemo()
' Create the delegate.
Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim result As IAsyncResult = caller.BeginInvoke(3000, _
threadId, Nothing, Nothing)
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.
Dim returnValue As String = caller.EndInvoke(threadId, result)
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _
threadId, returnValue)
End Sub
End Class
End Namespace
'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.".
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.".
*/
#using <TestMethod.dll>
using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;
void main()
{
// The asynchronous method puts the thread id here.
int threadId = 2546;
// Create an instance of the test class.
AsyncDemo^ ad = gcnew AsyncDemo();
// Create the delegate.
AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
// Initiate the asychronous call.
IAsyncResult^ result = caller->BeginInvoke(3000,
threadId, nullptr, nullptr);
Thread::Sleep(1);
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(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.".
*/
等待有 WaitHandle 的非同步呼叫
只要使用由 BeginInvoke 傳回之 IAsyncResult 的 AsyncWaitHandle 屬性,您就可以取得 WaitHandle。WaitHandle 會在非同步呼叫完成時收到信號,您可以呼叫 WaitOne 方法以等候此處理常式。
如果使用 WaitHandle,您就能在非同步呼叫完成的前後執行額外的處理,不過這些處理必須在呼叫 EndInvoke 以擷取結果之前進行。
注意事項: |
---|
當您呼叫 EndInvoke 時,等候控制代碼不會自動關閉。如果您釋放所有對等候控制代碼的參考,當記憶體回收將等候控制代碼回收時,會釋放系統資源。若要在使用完等候控制代碼時即釋放系統資源,請呼叫 WaitHandle.Close 方法來處置它。當可處置的物件明確處置時,記憶體回收的運作會更有效率。 |
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Namespace Examples.AdvancedProgramming.AsynchronousOperations
Public Class AsyncMain
Shared Sub Main()
' The asynchronous method puts the thread id here.
Dim threadId As Integer
' Create an instance of the test class.
Dim ad As New AsyncDemo()
' Create the delegate.
Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim result As IAsyncResult = caller.BeginInvoke(3000, _
threadId, Nothing, Nothing)
Thread.Sleep(0)
Console.WriteLine("Main thread {0} does some work.", _
Thread.CurrentThread.ManagedThreadId)
' Perform additional processing here and then
' wait for the WaitHandle to be signaled.
result.AsyncWaitHandle.WaitOne()
' Call EndInvoke to retrieve the results.
Dim returnValue As String = caller.EndInvoke(threadId, result)
' Close the wait handle.
result.AsyncWaitHandle.Close()
Console.WriteLine("The call executed on thread {0}, with return value ""{1}"".", _
threadId, returnValue)
End Sub
End Class
End Namespace
'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.".
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.".
*/
#using <TestMethod.dll>
using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;
void main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo^ ad = gcnew AsyncDemo();
// Create the delegate.
AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
// Initiate the asychronous call.
IAsyncResult^ result = caller->BeginInvoke(3000,
threadId, nullptr, nullptr);
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(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.".
*/
輪詢非同步呼叫完成
您可以使用由 BeginInvoke 傳回之 IAsyncResult 的 IsCompleted 屬性,來探索非同步呼叫完成的時間。您可能會在從服務使用者介面的執行緒進行非同步呼叫時,執行這項工作。針對完成而進行的輪詢,能讓呼叫的執行緒繼續執行,並在同時能對 ThreadPool 執行緒執行非同步呼叫。
Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Namespace Examples.AdvancedProgramming.AsynchronousOperations
Public Class AsyncMain
Shared Sub Main()
' The asynchronous method puts the thread id here.
Dim threadId As Integer
' Create an instance of the test class.
Dim ad As New AsyncDemo()
' Create the delegate.
Dim caller As New AsyncMethodCaller(AddressOf ad.TestMethod)
' Initiate the asynchronous call.
Dim result As IAsyncResult = caller.BeginInvoke(3000, _
threadId, Nothing, Nothing)
' Poll while simulating work.
While result.IsCompleted = False
Thread.Sleep(250)
Console.Write(".")
End While
' Call EndInvoke to retrieve the results.
Dim returnValue As String = caller.EndInvoke(threadId, result)
Console.WriteLine(vbCrLf & _
"The call executed on thread {0}, with return value ""{1}"".", _
threadId, returnValue)
End Sub
End Class
End Namespace
' 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.".
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.".
*/
#using <TestMethod.dll>
using namespace System;
using namespace System::Threading;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;
void main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo^ ad = gcnew AsyncDemo();
// Create the delegate.
AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::TestMethod);
// Initiate the asychronous call.
IAsyncResult^ result = caller->BeginInvoke(3000,
threadId, nullptr, nullptr);
// Poll while simulating work.
while(result->IsCompleted == false)
{
Thread::Sleep(250);
Console::Write(".");
}
// Call EndInvoke to retrieve the results.
String^ returnValue = caller->EndInvoke(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.".
*/
非同步呼叫完成時執行回呼方法
如果啟始非同步呼叫的執行緒,不需要是處理結果的執行緒,您就可以在呼叫完成時執行回呼方法。回呼方法會在 ThreadPool 執行緒上執行。
若要使用回呼方法,您必須將代表回呼方法的 AsyncCallback 委派,傳遞給 BeginInvoke。您也可以傳遞物件,其中包含要由回呼方法使用的資訊。在回呼方法中,您可以將回呼方法的唯一參數 IAsyncResult 轉換成 AsyncResult 物件。您接著可以使用 AsyncResult.AsyncDelegate 屬性取得用來啟始呼叫的委派,以便能夠呼叫 EndInvoke。
範例附註:
TestMethod 的 threadId 參數是 out 參數 (Visual Basic 中的 <Out> ByRef),因此 TestMethod 永遠不會使用它的輸入值。空的變數會傳遞到 BeginInvoke 呼叫。如果 threadId 參數是 ref 參數 (Visual Basic 中的 ByRef),變數就必須是類別層級的欄位,以便能同時傳遞給 BeginInvoke 和 EndInvoke。
傳遞給 BeginInvoke 的狀態資訊是格式字串,回呼方法會用來格式化輸出訊息。狀態資訊是以型別 Object 來傳遞,因此必須先將其轉型為適當型別後才能使用。
回呼是在 ThreadPool 執行緒上進行的。ThreadPool 執行緒是背景執行緒,如果主執行緒結束,就不會使應用程式保持在執行中,因此範例的主執行緒的休眠時間必須夠長,讓回呼得以完成。
Imports System
Imports System.Threading
Imports System.Runtime.Remoting.Messaging
Namespace Examples.AdvancedProgramming.AsynchronousOperations
Public Class AsyncMain
Shared Sub Main()
' Create an instance of the test class.
Dim ad As New AsyncDemo()
' Create the delegate.
Dim caller As New AsyncMethodCaller(AddressOf 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 ByRef parameter, it would have to be a class-
' level field so that it could be passed to both BeginInvoke and
' EndInvoke.
Dim dummy As Integer = 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.
Dim result As IAsyncResult = caller.BeginInvoke(3000, _
dummy, _
AddressOf 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.")
End Sub
' The callback method must have the same signature as the
' AsyncCallback delegate.
Shared Sub CallbackMethod(ByVal ar As IAsyncResult)
' Retrieve the delegate.
Dim result As AsyncResult = CType(ar, AsyncResult)
Dim caller As AsyncMethodCaller = CType(result.AsyncDelegate, AsyncMethodCaller)
' Retrieve the format string that was passed as state
' information.
Dim formatString As String = CType(ar.AsyncState, String)
' Define a variable to receive the value of the <Out> parameter.
' If the parameter were ByRef rather than <Out> then it would have to
' be a class-level field so it could also be passed to BeginInvoke.
Dim threadId As Integer = 0
' Call EndInvoke to retrieve the results.
Dim returnValue As String = caller.EndInvoke(threadId, ar)
' Use the format string to format the output message.
Console.WriteLine(formatString, threadId, returnValue)
End Sub
End Class
End Namespace
' 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.
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.
*/
#using <TestMethod.dll>
using namespace System;
using namespace System::Threading;
using namespace System::Runtime::Remoting::Messaging;
using namespace Examples::AdvancedProgramming::AsynchronousOperations;
// The callback method must have the same signature as the
// AsyncCallback delegate.
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(threadId, ar);
// Use the format string to format the output message.
Console::WriteLine(formatString, threadId, returnValue);
};
void main()
{
// Create an instance of the test class.
AsyncDemo^ ad = gcnew AsyncDemo();
// Create the delegate.
AsyncMethodCaller^ caller = gcnew AsyncMethodCaller(ad, &AsyncDemo::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,
dummy,
gcnew 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.");
}
/* 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.
*/
請參閱
參考
其他資源
變更記錄
日期 |
記錄 |
原因 |
---|---|---|
2008 年 7 月 |
更新等候 WaitHandle 以處置等候控制代碼的程式碼。加入關於處置等候控制代碼的附註。 |
客戶回函。 |