Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
.NET, herhangi bir yöntemi zaman uyumsuz olarak çağırmanızı sağlar. Bunu yapmak için, çağırmak istediğiniz yöntemle aynı imzaya sahip bir temsilci tanımlarsınız. Ortak dil çalışma zamanı, bu temsilci için BeginInvoke ve EndInvoke yöntemlerini uygun imzalarla otomatik olarak tanımlar.
Not
Zaman uyumsuz temsilci çağrıları( özellikle BeginInvoke ve EndInvoke yöntemleri) .NET Compact Framework'te desteklenmez.
BeginInvoke yöntemi zaman uyumsuz çağrıyı başlatır. Zaman uyumsuz olarak yürütmek istediğiniz yöntemle aynı parametrelere ve ek olarak isteğe bağlı iki parametreye sahiptir. İlk parametre, zaman uyumsuz çağrı tamamlandığında çağrılacak bir yöntemi referans alan bir AsyncCallback temsilcidir. İkinci parametre, bilgileri geri çağırma yöntemine geçiren kullanıcı tanımlı bir nesnedir.
BeginInvoke hemen geri döner ve zaman uyumsuz çağrının tamamlanmasını beklemez.
BeginInvoke , zaman uyumsuz çağrının ilerleme durumunu izlemek için kullanılabilecek bir IAsyncResult döndürür.
EndInvoke metodu, zaman uyumsuz çağrının sonuçlarını alır. 'den sonra BeginInvokeherhangi bir zaman çağrılabilir. Zaman uyumsuz çağrı tamamlanmadıysa, EndInvoke tamamlanana kadar çağrı iş parçacığını engeller. parametreleri EndInvoke zaman uyumsuz olarak yürütmek istediğiniz yöntemin out parametrelerini (ref<Out> ve Visual Basic'te ByRef) ve ByRef tarafından döndürülen IAsyncResult'yı içerir.
Not
Visual Studio'daki IntelliSense özelliği, BeginInvoke ve EndInvoke parametrelerini görüntüler. Visual Studio veya benzer bir araç kullanmıyorsanız veya Visual Studio ile C# kullanıyorsanız, bu yöntemler için tanımlanan parametrelerin açıklaması için bkz. Zaman Uyumsuz Programlama Modeli (APM).
Bu konudaki kod örnekleri, BeginInvoke ve EndInvoke kullanarak zaman uyumsuz çağrılar yapmanın dört yaygın yolunu göstermektedir. Aradıktan BeginInvoke sonra aşağıdakileri yapabilirsiniz:
Biraz iş yapın ve ardından arama
EndInvoketamamlanana kadar engelleme çağrısı yapın.WaitHandle özelliğini kullanarak bir IAsyncResult.AsyncWaitHandle alın, WaitOne sinyali alındığında kadar yürütmeyi engellemek için WaitHandle yöntemini kullanın ve ardından
EndInvokeçağrısını yapın.Asenkron çağrının tamamlandığını belirlemek için IAsyncResult tarafından döndürülen
BeginInvokeöğesini yoklayın ve ardındanEndInvoke'yi çağırın.Geri çağırma metodu için bir delegeyi
BeginInvokeöğesine geçirin. Zaman uyumsuz çağrı tamamlandığında yöntem bir ThreadPool iş parçacığında yürütülür. Callback yöntemiEndInvoke'yi çağırır.
Önemli
Hangi tekniği kullanırsanız kullanın, zaman uyumsuz çağrınızı tamamlamak için her zaman EndInvoke çağırın.
Test Yöntemini ve Asenkron Delegeyi Tanımlama
Aşağıdaki kod örnekleri, aynı uzun süre çalışan yöntemini TestMethodzaman uyumsuz olarak çağırmanın çeşitli yollarını gösterir.
TestMethod yöntemi, işlemeye başladığını, birkaç saniye boyunca uykuda olduğunu ve ardından sona erdiğini göstermek için bir konsol iletisi görüntüler.
TestMethod, ve outimzalarına BeginInvoke bu tür parametrelerin nasıl eklendiğini gösteren bir EndInvoke parametreye sahiptir.
ref parametreleri benzer şekilde işleyebilirsiniz.
Aşağıdaki kod örneği, zaman uyumsuz olarak TestMethod çağırmak için kullanılabilecek AsyncMethodCaller adlı temsilci ile TestMethod tanımını gösterir. Kod örneklerini derlemek için TestMethod ve AsyncMethodCaller temsilcisinin tanımlarını eklemeniz gerekir.
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);
}
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
EndInvoke ile Asenkron Çağrıyı Bekleme
Bir yöntemi zaman uyumsuz olarak yürütmenin en basit yolu, temsilcinin BeginInvoke yöntemini çağırarak yöntemini yürütmeye başlamak, ana iş parçacığında bazı çalışmalar yapmak ve sonra temsilcinin yöntemini çağırmaktır EndInvoke .
EndInvoke zaman uyumsuz çağrı tamamlanana kadar döndürülmediğinden çağıran iş parçacığını engelleyebilir. Bu, dosya veya ağ işlemleriyle kullanmak için iyi bir tekniktir.
Önemli
Engelleyebileceğinden EndInvoke , bunu kullanıcı arabirimine hizmet veren iş parçacıklarından asla çağırmamalısınız.
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain3
{
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 asynchronous call.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine($"Main thread {Thread.CurrentThread.ManagedThreadId} does some work.");
// 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.".
*/
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.".
WaitHandle ile Eşzamansız Çağrı Bekleme
WaitHandle tarafından döndürülen AsyncWaitHandle'nin IAsyncResult özelliğini kullanarak bir BeginInvoke elde edebilirsiniz.
WaitHandle, zaman uyumsuz çağrı tamamlandığında sinyali verir ve WaitOne yöntemini çağırarak bunu bekleyebilirsiniz.
Eğer bir WaitHandle kullanıyorsanız, zaman uyumsuz çağrı tamamlanmadan önce veya tamamlandıktan sonra, ancak sonuçları almak için EndInvoke çağrılmadan önce ek işlemler gerçekleştirebilirsiniz.
Not
çağırdığınızda EndInvokebekleme tutamacı otomatik olarak kapatılmaz. Bekleme tutamaçlarına yapılan tüm başvuruları serbest bırakırsanız, çöp toplama bekleme tutamacını geri kazandığında sistem kaynakları serbest bırakılır. Bekleme tutamacını kullanmayı bitirdiğinizde sistem kaynaklarını boşaltmak için WaitHandle.Close yöntemini çağırarak bu kaynağı bırakın. Atık toplama, atılabilir nesneler açıkça atıldığında daha verimli çalışır.
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain2
{
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 asynchronous call.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine($"Main thread {Thread.CurrentThread.ManagedThreadId} does some work.");
// 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.".
*/
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.".
Asenkron Çağrı Tamamlaması için Anket Yapma
Asenkron çağrının ne zaman tamamlandığını keşfetmek için IsCompleted tarafından döndürülen IAsyncResult'ın BeginInvoke özelliğini kullanabilirsiniz. Zaman uyumsuz çağrı yaparken, kullanıcı arabirimine hizmet veren bir iş parçacığından bunu yapabilirsiniz. Tamamlanma durumunun yoklanması, zaman uyumsuz çağrı bir ThreadPool iş parçacığında yürütülürken, çağıran iş parçacığının çalışmaya devam etmesini sağlar.
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 asynchronous 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.".
*/
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.".
Zaman Uyumsuz Çağrı Tamamlandığında Geri Çağırma Yöntemi Yürütme
Zaman uyumsuz çağrıyı başlatan iş parçacığının sonuçları işleyen iş parçacığı olması gerekmiyorsa, çağrı tamamlandığında bir geri çağırma yöntemi yürütebilirsiniz. Geri çağırma yöntemi bir ThreadPool iş parçacığında yürütülür.
Geri çağırma yöntemini kullanmak için bu yöntemi temsil eden bir BeginInvoke temsilci AsyncCallback geçirmeniz gerekir. Geri çağırma yöntemi tarafından kullanılacak bilgileri içeren bir nesneyi de geçirebilirsiniz. Geri çağırma yönteminde, geri çağırma yönteminin tek parametresi olan öğesini bir IAsyncResult nesneye dönüştürebilirsinizAsyncResult. Daha sonra, bir çağrıyı başlatmak için kullanılan AsyncResult.AsyncDelegate temsilcisini almak amacıyla bu özelliği kullanabilir ve böylece EndInvoke öğesini çağırabilirsiniz.
Örnekteki notlar:
threadIdparametresi,TestMethod'nin biroutparametresidir (Visual Basic'te [<Out>ByRef]), bu nedenle giriş değeri hiçbir zamanTestMethodtarafından kullanılmaz. ÇağrıyaBeginInvokesahte bir değişken geçirilir.threadIdParametre birrefparametreyse (ByRefVisual Basic'te), değişkenin, hemBeginInvokehem deEndInvokeöğesine geçirilebilmesi için sınıf düzeyinde bir alan olması gerekirdi.geçirilen
BeginInvokedurum bilgileri, geri çağırma yönteminin bir çıkış iletisini biçimlendirmek için kullandığı bir biçim dizesidir. türü Objectolarak geçirildiğinden, durum bilgilerinin kullanılabilmesi için önce uygun türüne geçirilmesi gerekir.Geri çağırma, bir ThreadPool thread'inde yapılır. ThreadPool iş parçacıkları, ana iş parçacığı sona erdiğinde uygulamayı çalışır durumda tutmayan arka plan iş parçacıklarıdır, bu nedenle örneğin ana iş parçacığının geri çağırmanın bitmesi için yeterince uzun bir süre uykuda kalması gerekir.
using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain4
{
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 {Thread.CurrentThread.ManagedThreadId} continues to execute...");
// 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.
*/
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.