مشاركة عبر


الإرشادات التفصيلية: تنفيذ مكونات التي تعتمد حدث-إلى نقش غير متزامن

If you are writing a فئة مع some العمليات that may incur noticeable delays, consider giving it غير متزامن functionality بواسطة implementing the نظرة عامة تستند إلى حدث غير متزامن نقش حول.

This معاينة illustrates how إلى إنشاء a مكوّن that implements the حدث-based نمط غير متزامن. It هو implemented using helper فئات من the System.ComponentModel مساحة الاسم, which ensures that the مكوّن works correctly under أي نمط تطبيق, including ASP.NET, Console applications و Windows Forms applications. This مكوّن هو also designable مع a PropertyGrid عنصر تحكم و your own مخصص designers.

When you are through, you will have an تطبيق that computes prime أرقام asynchronously. Your تطبيق will have a main مستخدم واجهة (واجه المستخدم) مؤشر ترابط و a مؤشر ترابط for each prime رقم calculation. Although testing whether a قطر أيمن متوسط رقم هو prime can take a noticeable المقدار of الوقت, the main مؤشر ترابط وجهه المستخدم will not be interrupted بواسطة this تأخير, و the نموذج will be responsive during the calculations. You will be able إلى تشغيل كـ many calculations كـ you مثل concurrently و selectively إلغاء الأمر معلّقة calculations.

تتضمن المهام الموضحة في هذه الإرشادات التفصيلية ما يلي:

  • Creating the مكوّن

  • Defining Public غير متزامن أحداث و المفوضون

  • Defining Private المفوضون

  • Implementing Public أحداث

  • Implementing the Completion أسلوب

  • Implementing the Worker وظائف

  • تنفيذ أساليب ابدأ و إلغاء الأمر

لنسخ التعليمة البرمجية في هذا الموضوع كقائمة واحدة, راجع كيفية القيام بما يلي: تنفيذ مكوّن التي تعتمد على النقش غير متزامن يستند إلى حدث.

Creating the مكوّن

الخطوة الأولى هو لإنشاء المكونات التي سيتم تطبيق "نقش غير متزامن" تستند إلى الحدث.

إلى إنشاء مكوّن

  • إنشاء فئة تسمى PrimeNumberCalculatorالتي ترث من Component.

Defining Public غير متزامن أحداث و المفوضون

الخاص بك مكوّن يتواصل للعملاء الذين يستخدمون الأحداث. تنبيهات حدث MethodNameCompleted العملاء بالإكمال غير متزامن المهمة، وحدث MethodNameProgressChanged إعلام العملاء للتقدم من غير متزامن المهمة.

لتعريف غير متزامن الأحداث لعملاء مكوّن الخاص بك:

  1. استيراد من System.Threadingو System.Collections.Specializedمساحات الاسم في أعلى الملف الخاص بك.

    Imports System
    Imports System.Collections
    Imports System.Collections.Specialized
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Globalization
    Imports System.Threading
    Imports System.Windows.Forms
    
    using System;
    using System.Collections;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Globalization;
    using System.Threading;
    using System.Windows.Forms;
    
  2. قبل PrimeNumberCalculator تعريف الفئة، قم بتعريف المفوضون للتقدم واكتمال الأحداث.

    Public Delegate Sub ProgressChangedEventHandler( _
        ByVal e As ProgressChangedEventArgs)
    
    Public Delegate Sub CalculatePrimeCompletedEventHandler( _
        ByVal sender As Object, _
        ByVal e As CalculatePrimeCompletedEventArgs)
    
    public delegate void ProgressChangedEventHandler(
        ProgressChangedEventArgs e);
    
    public delegate void CalculatePrimeCompletedEventHandler(
        object sender,
        CalculatePrimeCompletedEventArgs e);
    
  3. في PrimeNumberCalculator تعريف فئة، تقوم بتعريف الأحداث للإبلاغ عن التقدم وإتمام إلى العملاء.

    Public Event ProgressChanged _
        As ProgressChangedEventHandler
    Public Event CalculatePrimeCompleted _
        As CalculatePrimeCompletedEventHandler
    
    public event ProgressChangedEventHandler ProgressChanged;
    public event CalculatePrimeCompletedEventHandler CalculatePrimeCompleted;
    
  4. بعد PrimeNumberCalculator تعريف الفئة، اشتقاق CalculatePrimeCompletedEventArgs فئة لإرساله تقريرا بنتيجة عملية حسابية كل إلى معالج الأحداث الخاص بالعميل CalculatePrimeCompleted.حدث. بالإضافة إلى AsyncCompletedEventArgsالخصائص، رقم هو فئة تمكن العميل لتحديد الرقم الذي تم اختباره، سواء من هو تحقيق، وما هي divهوor أول هو إذا هو غير أساسي.

    Public Class CalculatePrimeCompletedEventArgs
        Inherits AsyncCompletedEventArgs
        Private numberToTestValue As Integer = 0
        Private firstDivisorValue As Integer = 1
        Private isPrimeValue As Boolean
    
    
        Public Sub New( _
        ByVal numberToTest As Integer, _
        ByVal firstDivisor As Integer, _
        ByVal isPrime As Boolean, _
        ByVal e As Exception, _
        ByVal canceled As Boolean, _
        ByVal state As Object)
    
            MyBase.New(e, canceled, state)
            Me.numberToTestValue = numberToTest
            Me.firstDivisorValue = firstDivisor
            Me.isPrimeValue = isPrime
    
        End Sub
    
    
        Public ReadOnly Property NumberToTest() As Integer
            Get
                ' Raise an exception if the operation failed 
                ' or was canceled.
                RaiseExceptionIfNecessary()
    
                ' If the operation was successful, return 
                ' the property value.
                Return numberToTestValue
            End Get
        End Property
    
    
        Public ReadOnly Property FirstDivisor() As Integer
            Get
                ' Raise an exception if the operation failed 
                ' or was canceled.
                RaiseExceptionIfNecessary()
    
                ' If the operation was successful, return 
                ' the property value.
                Return firstDivisorValue
            End Get
        End Property
    
    
        Public ReadOnly Property IsPrime() As Boolean
            Get
                ' Raise an exception if the operation failed 
                ' or was canceled.
                RaiseExceptionIfNecessary()
    
                ' If the operation was successful, return 
                ' the property value.
                Return isPrimeValue
            End Get
        End Property
    End Class
    
        public class CalculatePrimeCompletedEventArgs :
            AsyncCompletedEventArgs
        {
            private int numberToTestValue = 0;
            private int firstDivisorValue = 1;
            private bool isPrimeValue;
    
            public CalculatePrimeCompletedEventArgs(
                int numberToTest,
                int firstDivisor,
                bool isPrime,
                Exception e,
                bool canceled,
                object state) : base(e, canceled, state)
            {
                this.numberToTestValue = numberToTest;
                this.firstDivisorValue = firstDivisor;
                this.isPrimeValue = isPrime;
            }
    
            public int NumberToTest
            {
                get
                {
                    // Raise an exception if the operation failed or 
                    // was canceled.
                    RaiseExceptionIfNecessary();
    
                    // If the operation was successful, return the 
                    // property value.
                    return numberToTestValue;
                }
            }
    
            public int FirstDivisor
            {
                get
                {
                    // Raise an exception if the operation failed or 
                    // was canceled.
                    RaiseExceptionIfNecessary();
    
                    // If the operation was successful, return the 
                    // property value.
                    return firstDivisorValue;
                }
            }
    
            public bool IsPrime
            {
                get
                {
                    // Raise an exception if the operation failed or 
                    // was canceled.
                    RaiseExceptionIfNecessary();
    
                    // If the operation was successful, return the 
                    // property value.
                    return isPrimeValue;
                }
            }
        }
    
    

Checkpoint (نقطة التحقق)

عند هذه النقطة، يمكنك بنية مكوّن.

إلى اختبار مكوّن الخاص بك

  • ترجمة مكوّن.

    سوف تتلقى تحذيرات المحول البرمجي الثاني:

    warning CS0067: The event 'AsynchronousPatternExample.PrimeNumberCalculator.ProgressChanged' is never used
    warning CS0067: The event 'AsynchronousPatternExample.PrimeNumberCalculator.CalculatePrimeCompleted' is never used
    

    سيتم مسح هذه التحذيرات في مقطع التالي.

Defining Private المفوضون

غير متزامن أوجه PrimeNumberCalculator مكوّن المطبقة داخليا مع مفوض خاص يعرف SendOrPostCallback. SendOrPostCallbackيمثل أسلوب رد اتصال التي تنفذ في ThreadPoolمؤشر ترابط. يجب أن يكون الأسلوب رد الاتصال لتوقيع التي تأخذ معلمة واحدة من نوع Object، مما يعني أنك بحاجة إلى تمرير الولاية بين المفوضون في فئة. مجمع لمزيد من المعلومات، راجع SendOrPostCallback.

لتنفيذ المكون الخاص بك للداخلية غير متزامن سلوك:

  1. قم بتعريف و إنشاء SendOrPostCallbackالمفوضون في PrimeNumberCalculator فئة. إنشاء SendOrPostCallbackالكائنات في أسلوب أداة مساعدة تسمى InitializeDelegates.

    يجب مفوضين الثاني: التقارير للعميل، والآخر ل التقارير الاكتمال إلى العميل.

    Private onProgressReportDelegate As SendOrPostCallback
    Private onCompletedDelegate As SendOrPostCallback
    
    
    ...
    
    
    Protected Overridable Sub InitializeDelegates()
        onProgressReportDelegate = _
            New SendOrPostCallback(AddressOf ReportProgress)
        onCompletedDelegate = _
            New SendOrPostCallback(AddressOf CalculateCompleted)
    End Sub
    
    private SendOrPostCallback onProgressReportDelegate;
    private SendOrPostCallback onCompletedDelegate;
    
    
    ...
    
    
    protected virtual void InitializeDelegates()
    {
        onProgressReportDelegate =
            new SendOrPostCallback(ReportProgress);
        onCompletedDelegate =
            new SendOrPostCallback(CalculateCompleted);
    }
    
  2. استدعاء InitializeDelegatesالأسلوب في الدالة الإنشائية مكوّن's.

    Public Sub New()
    
        InitializeComponent()
    
        InitializeDelegates()
    
    End Sub
    
    public PrimeNumberCalculator()
    {   
        InitializeComponent();
    
        InitializeDelegates();
    }
    
  3. قم بتعريف مفوض في PrimeNumberCalculatorالفئة التي يتعامل مع العمل الفعلي إلى إنجازه بشكل غير متزامن. Th هو يلتف المفوض الأسلوب العامل الذي اختبار ما إذا كان رقم هو تحقيق. The delegate takes an AsyncOperation parameter, which will be used إلى track the lifetime of the غير متزامن operation.

    Private Delegate Sub WorkerEventHandler( _
    ByVal numberToCheck As Integer, _
    ByVal asyncOp As AsyncOperation)
    
    private delegate void WorkerEventHandler(
        int numberToCheck,
        AsyncOperation asyncOp);
    
  4. إنشاء مجموعة لإدارة إعمار من العمليات غير المتزامنة المعلقة. The client needs a way إلى track العمليات as they are executed and completed, and this tracking هو done by requiring the client إلى pass a unique إلىken, or معرف المهمة, when the client makes the call إلى the غير متزامن method. PrimeNumberCalculatorمكونات يجب التمكن من مقطع صوتي كل استدعاء بواسطة إقران المعرف مهمة مع به الاستدعاء المطابق. إذا مرت العميل المعرف المهمة غير فريد، PrimeNumberCalculatorيجب رفع المكون على ‏‏ استثناء.

    PrimeNumberCalculatorيحتفظ مقطع صوتي لمكون معرف مهمة باستخدام فئة خاص لمجموعة ما يسمى HybridDictionary. في تعريف الفئة، قم بإنشاء على HybridDictionaryيسمى userTokenToLifetime.

    Private userStateToLifetime As New HybridDictionary()
    
    private HybridDictionary userStateToLifetime = 
        new HybridDictionary();
    

Implementing Public أحداث

المكونات التي تقوم بتطبيق "نقش غير متزامن" يستند إلى حدث الاتصال للعملاء الذين يستخدمون أحداث. هذه أحداث يتم استدعاء تشغيل مؤشر ترابط الصحيح بمساعدة AsyncOperationفئة.

إلى raise events إلى your مكوّن's clients:

  • قم بتطبيق أحداث العام للتقرير للعملاء. ستحتاج إلى حدث للإبلاغ عن التقدم والآخر للاكتمال التقارير.

    ' This method is invoked via the AsyncOperation object,
    ' so it is guaranteed to be executed on the correct thread.
    Private Sub CalculateCompleted(ByVal operationState As Object)
        Dim e As CalculatePrimeCompletedEventArgs = operationState
    
        OnCalculatePrimeCompleted(e)
    
    End Sub
    
    
    ' This method is invoked via the AsyncOperation object,
    ' so it is guaranteed to be executed on the correct thread.
    Private Sub ReportProgress(ByVal state As Object)
        Dim e As ProgressChangedEventArgs = state
    
        OnProgressChanged(e)
    
    End Sub
    
    Protected Sub OnCalculatePrimeCompleted( _
        ByVal e As CalculatePrimeCompletedEventArgs)
    
        RaiseEvent CalculatePrimeCompleted(Me, e)
    
    End Sub
    
    
    Protected Sub OnProgressChanged( _
        ByVal e As ProgressChangedEventArgs)
    
        RaiseEvent ProgressChanged(e)
    
    End Sub
    
    // This method is invoked via the AsyncOperation object,
    // so it is guaranteed to be executed on the correct thread.
    private void CalculateCompleted(object operationState)
    {
        CalculatePrimeCompletedEventArgs e =
            operationState as CalculatePrimeCompletedEventArgs;
    
        OnCalculatePrimeCompleted(e);
    }
    
    // This method is invoked via the AsyncOperation object,
    // so it is guaranteed to be executed on the correct thread.
    private void ReportProgress(object state)
    {
        ProgressChangedEventArgs e =
            state as ProgressChangedEventArgs;
    
        OnProgressChanged(e);
    }
    
    protected void OnCalculatePrimeCompleted(
        CalculatePrimeCompletedEventArgs e)
    {
        if (CalculatePrimeCompleted != null)
        {
            CalculatePrimeCompleted(this, e);
        }
    }
    
    protected void OnProgressChanged(ProgressChangedEventArgs e)
    {
        if (ProgressChanged != null)
        {
            ProgressChanged(e);
        }
    }
    

Implementing the Completion أسلوب

The completion تفويض هو the أسلوب that the underlying, حر-threaded غير متزامن سلوك will invoke when the غير متزامن تشغيل ends بواسطة successful completion, خطأ, أو cancellation. This invocation happens تشغيل an arbitrary مؤشر ترابط.

This أسلوب هو الموقع the العميل's مهمة المعرف هو تمت إزالته من the internal مجموعة of فريد العميل رموز مميزة. This أسلوب also ends the مدة بقاء of a particular غير متزامن operation بواسطة calling the PostOperationCompleted أسلوب تشغيل the corresponding AsyncOperation. This يتصل raises the completion حدث تشغيل the مؤشر ترابط that هو appropriate for the نمط تطبيق. بعد the PostOperationCompleted أسلوب هو called, this مثيل of AsyncOperation can لا longer be used, و أي subsequent attempts إلى استخدم it will رمى an ‏‏ استثناء.

The CompletionMethod توقيع must تقييد الجميع الولاية necessary إلى describe the outcome of the غير متزامن تشغيل. It holds الولاية for the رقم that was tested بواسطة this particular غير متزامن تشغيل, whether the رقم هو prime, و the القيمة of its أول divisor if it ليس a prime رقم. It also holds الولاية describing أي ‏‏ استثناء that occurred, و the AsyncOperation corresponding إلى this particular مهمة.

لإكمال غير متزامن العملية:

  • الاكتمال تنفيذ أسلوب. فإنه يأخذ معلمات الستة، والتي تستخدم لتجميع CalculatePrimeCompletedEventArgsالتي هو التي يتم إرجاعها للعميل من خلال العميل CalculatePrimeCompletedEventHandler. يقوم بإزالة العميل المعرف مهمة رمز مميز من المجموعة الداخلية، وتنتهي مدة تشغيل غير المتزامنة بواسطة استدعاء PostOperationCompleted. AsyncOperationmarshals استدعاء مؤشر ترابط أو سياق الذي هو مناسبة لطراز تطبيق.

    ' This is the method that the underlying, free-threaded 
    ' asynchronous behavior will invoke.  This will happen on
    '  an arbitrary thread.
    Private Sub CompletionMethod( _
        ByVal numberToTest As Integer, _
        ByVal firstDivisor As Integer, _
        ByVal prime As Boolean, _
        ByVal exc As Exception, _
        ByVal canceled As Boolean, _
        ByVal asyncOp As AsyncOperation)
    
        ' If the task was not previously canceled,
        ' remove the task from the lifetime collection.
        If Not canceled Then
            SyncLock userStateToLifetime.SyncRoot
                userStateToLifetime.Remove(asyncOp.UserSuppliedState)
            End SyncLock
        End If
    
        ' Package the results of the operation in a 
        ' CalculatePrimeCompletedEventArgs.
        Dim e As New CalculatePrimeCompletedEventArgs( _
            numberToTest, _
            firstDivisor, _
            prime, _
            exc, _
            canceled, _
            asyncOp.UserSuppliedState)
    
        ' End the task. The asyncOp object is responsible 
        ' for marshaling the call.
        asyncOp.PostOperationCompleted(onCompletedDelegate, e)
    
        ' Note that after the call to PostOperationCompleted, asyncOp
        ' is no longer usable, and any attempt to use it will cause.
        ' an exception to be thrown.
    
    End Sub
    
    // This is the method that the underlying, free-threaded 
    // asynchronous behavior will invoke.  This will happen on
    // an arbitrary thread.
    private void CompletionMethod( 
        int numberToTest,
        int firstDivisor, 
        bool isPrime,
        Exception exception, 
        bool canceled,
        AsyncOperation asyncOp )
    
    {
        // If the task was not previously canceled,
        // remove the task from the lifetime collection.
        if (!canceled)
        {
            lock (userStateToLifetime.SyncRoot)
            {
                userStateToLifetime.Remove(asyncOp.UserSuppliedState);
            }
        }
    
        // Package the results of the operation in a 
        // CalculatePrimeCompletedEventArgs.
        CalculatePrimeCompletedEventArgs e =
            new CalculatePrimeCompletedEventArgs(
            numberToTest,
            firstDivisor,
            isPrime,
            exception,
            canceled,
            asyncOp.UserSuppliedState);
    
        // End the task. The asyncOp object is responsible 
        // for marshaling the call.
        asyncOp.PostOperationCompleted(onCompletedDelegate, e);
    
        // Note that after the call to OperationCompleted, 
        // asyncOp is no longer usable, and any attempt to use it
        // will cause an exception to be thrown.
    }
    

Checkpoint (نقطة التحقق)

عند هذه النقطة، يمكنك بنية مكوّن.

إلى اختبار مكوّن الخاص بك

  • ترجمة مكوّن.

    سوف تتلقى تحذير برنامج التحويل البرمجي واحد:

    warning CS0169: The private field 'AsynchronousPatternExample.PrimeNumberCalculator.workerDelegate' is never used
    

    سيتم حل هذا التحذير في مقطع التالي.

Implementing the Worker وظائف

حتى الآن، طبقت دعم غير متزامن التعليمة البرمجية ل PrimeNumberCalculatorمكوّن. الآن يمكنك تنفيذ تعليمات برمجية التي يقوم العمل الفعلي. سيتم تطبيق ثلاث طرق: CalculateWorker ، BuildPrimeNumberList و IsPrime مع بعضها، BuildPrimeNumberListو IsPrimecomprهوe تدعي خوارزمية معروفة في Sieve من Eratosthenes، وتحديد ما إذا كان رقم هو الأساسية بالبحث عن الجميع الأرقام الأولية إلى الجذر التربيعي لرقم الاختبار. إذا تم العثور على لا divهوors بتلك النقطة، رقم الاختبار هو تحقيق.

إذا تمت كتابتها هذا مكوّن للكفاءة القصوى، هل تذكر الجميع الأرقام الأولية التي تم اكتشافها بواسطة invocations المتنوعة لمختلف اختبار أرقام. أيضا تحقق من divisors العادية مثل 2 و 3 و 5. غرض th هو المثال هو لتوضيح كيفية يستغرق وقتاً طويلاً لعمليات يمكن تنفيذها بشكل غير متزامن، على الرغم من ذلك، حيث يتم ترك هذه تحسينات exercهوe نيابة عنك.

CalculateWorkerأسلوب هو الملتفة في مفوض و هو باستدعاء غير متزامن مع استدعاء BeginInvoke.

ملاحظةملاحظة

تقارير تقدم العمل هو في BuildPrimeNumberListالأسلوب.تشغيل أجهزة كمبيوتر سريع، ProgressChangedيمكن يمكن رفع أحداث في تتابع سريع.يجب أن يكون مؤشر ترابط العميل، بحيث يتم مرفوع هذه الأحداث، على إلى معالجة هذا الموقف.واجهة مستخدم قد يكون رمز flooded مع الرسائل وغير قادر على الاحتفاظ بالأعلى، مما يؤدي إلى سلوك المعلقة.لمثال واجهة مستخدم التي تعالج هذه الحالة، راجع كيفية القيام بما يلي: تطبيق عميل من حدث يستند غير متزامن نقش.

إلى تنفيذ العمليات الحسابية الرقم الأولية بشكل غير متزامن:

  1. تطبيق TaskCanceledأسلوب أداة مساعدة. هذا التحقق من مجموعة مدة مهمة للمعطى المعرف مهمة، وإرجاع trueإذا المعرف مهمة غير موجود.

    ' Utility method for determining if a 
    ' task has been canceled.
    Private Function TaskCanceled(ByVal taskId As Object) As Boolean
        Return (userStateToLifetime(taskId) Is Nothing)
    End Function
    
    // Utility method for determining if a 
    // task has been canceled.
    private bool TaskCanceled(object taskId)
    {
        return( userStateToLifetime[taskId] == null );
    }
    
  2. قم بتنفيذ الأسلوب CalculateWorker. يأخذ متغيرين: رقم إلى الاختبار، AsyncOperation.

    ' This method performs the actual prime number computation.
    ' It is executed on the worker thread.
    Private Sub CalculateWorker( _
        ByVal numberToTest As Integer, _
        ByVal asyncOp As AsyncOperation)
    
        Dim prime As Boolean = False
        Dim firstDivisor As Integer = 1
        Dim exc As Exception = Nothing
    
        ' Check that the task is still active.
        ' The operation may have been canceled before
        ' the thread was scheduled.
        If Not Me.TaskCanceled(asyncOp.UserSuppliedState) Then
    
            Try
                ' Find all the prime numbers up to the
                ' square root of numberToTest.
                Dim primes As ArrayList = BuildPrimeNumberList( _
                    numberToTest, asyncOp)
    
                ' Now we have a list of primes less than 
                'numberToTest.
                prime = IsPrime( _
                    primes, _
                    numberToTest, _
                    firstDivisor)
    
            Catch ex As Exception
                exc = ex
            End Try
    
        End If
    
        Me.CompletionMethod( _
            numberToTest, _
            firstDivisor, _
            prime, _
            exc, _
            TaskCanceled(asyncOp.UserSuppliedState), _
            asyncOp)
    
    End Sub
    
    // This method performs the actual prime number computation.
    // It is executed on the worker thread.
    private void CalculateWorker(
        int numberToTest,
        AsyncOperation asyncOp)
    {
        bool isPrime = false;
        int firstDivisor = 1;
        Exception e = null;
    
        // Check that the task is still active.
        // The operation may have been canceled before
        // the thread was scheduled.
        if (!TaskCanceled(asyncOp.UserSuppliedState))
        {
            try
            {
                // Find all the prime numbers up to 
                // the square root of numberToTest.
                ArrayList primes = BuildPrimeNumberList(
                    numberToTest,
                    asyncOp);
    
                // Now we have a list of primes less than
                // numberToTest.
                isPrime = IsPrime(
                    primes,
                    numberToTest,
                    out firstDivisor);
            }
            catch (Exception ex)
            {
                e = ex;
            }
        }
    
        //CalculatePrimeState calcState = new CalculatePrimeState(
        //        numberToTest,
        //        firstDivisor,
        //        isPrime,
        //        e,
        //        TaskCanceled(asyncOp.UserSuppliedState),
        //        asyncOp);
    
        //this.CompletionMethod(calcState);
    
        this.CompletionMethod(
            numberToTest,
            firstDivisor,
            isPrime,
            e,
            TaskCanceled(asyncOp.UserSuppliedState),
            asyncOp);
    
        //completionMethodDelegate(calcState);
    }
    
  3. التطبيق BuildPrimeNumberList يأخذ متغيرين: الرقم إلى الاختبار، AsyncOperation. فهو يستخدم AsyncOperationلتقرير التقدم و تزايدي النتائج. وتضمن هذه تسمى معالجات الأحداث العميل's تشغيل مؤشر ترابط الصحيح أو سياق للطراز تطبيق. عند BuildPrimeNumberListإيجاد رقم أساسي، فإنه يعلم هذا تزايدي نتيجة لمعالج الأحداث الخاص بالعميل ProgressChangedحدث. ويتطلب ذلك فئة مشتقة من ProgressChangedEventArgs، تسمى CalculatePrimeProgressChangedEventArgs، الذي قام واحد تمت الإضافة خاصية تسمى LatestPrimeNumber.

    BuildPrimeNumberListأيضا بشكل دوري باستدعاء أسلوب TaskCanceledأسلوب و يخرج إذا إرجاع الأسلوب true.

    ' This method computes the list of prime numbers used by the
    ' IsPrime method.
    Private Function BuildPrimeNumberList( _
        ByVal numberToTest As Integer, _
        ByVal asyncOp As AsyncOperation) As ArrayList
    
        Dim e As ProgressChangedEventArgs = Nothing
        Dim primes As New ArrayList
        Dim firstDivisor As Integer
        Dim n As Integer = 5
    
        ' Add the first prime numbers.
        primes.Add(2)
        primes.Add(3)
    
        ' Do the work.
        While n < numberToTest And _
            Not Me.TaskCanceled(asyncOp.UserSuppliedState)
    
            If IsPrime(primes, n, firstDivisor) Then
                ' Report to the client that you found a prime.
                e = New CalculatePrimeProgressChangedEventArgs( _
                    n, _
                    CSng(n) / CSng(numberToTest) * 100, _
                    asyncOp.UserSuppliedState)
    
                asyncOp.Post(Me.onProgressReportDelegate, e)
    
                primes.Add(n)
    
                ' Yield the rest of this time slice.
                Thread.Sleep(0)
            End If
    
            ' Skip even numbers.
            n += 2
    
        End While
    
        Return primes
    
    End Function
    
    // This method computes the list of prime numbers used by the
    // IsPrime method.
    private ArrayList BuildPrimeNumberList(
        int numberToTest,
        AsyncOperation asyncOp)
    {
        ProgressChangedEventArgs e = null;
        ArrayList primes = new ArrayList();
        int firstDivisor;
        int n = 5;
    
        // Add the first prime numbers.
        primes.Add(2);
        primes.Add(3);
    
        // Do the work.
        while (n < numberToTest && 
               !TaskCanceled( asyncOp.UserSuppliedState ) )
        {
            if (IsPrime(primes, n, out firstDivisor))
            {
                // Report to the client that a prime was found.
                e = new CalculatePrimeProgressChangedEventArgs(
                    n,
                    (int)((float)n / (float)numberToTest * 100),
                    asyncOp.UserSuppliedState);
    
                asyncOp.Post(this.onProgressReportDelegate, e);
    
                primes.Add(n);
    
                // Yield the rest of this time slice.
                Thread.Sleep(0);
            }
    
            // Skip even numbers.
            n += 2;
        }
    
        return primes;
    }
    
  4. التطبيق IsPrime يأخذ ثلاثة مدخلات: قائمة الإعداد الأولية المعروفة والرقم إلى الاختبار ومعلمة إخراج للعثور على المقسوم عليه أولاً. إعطاء lهوt الإعداد الأولية، فإنه يحدد إذا كان رقم الاختبار هو تحقيق.

    ' This method tests n for primality against the list of 
    ' prime numbers contained in the primes parameter.
    Private Function IsPrime( _
        ByVal primes As ArrayList, _
        ByVal n As Integer, _
        ByRef firstDivisor As Integer) As Boolean
    
        Dim foundDivisor As Boolean = False
        Dim exceedsSquareRoot As Boolean = False
    
        Dim i As Integer = 0
        Dim divisor As Integer = 0
        firstDivisor = 1
    
        ' Stop the search if:
        ' there are no more primes in the list,
        ' there is a divisor of n in the list, or
        ' there is a prime that is larger than 
        ' the square root of n.
        While i < primes.Count AndAlso _
            Not foundDivisor AndAlso _
            Not exceedsSquareRoot
    
            ' The divisor variable will be the smallest prime number 
            ' not yet tried.
            divisor = primes(i)
            i = i + 1
    
            ' Determine whether the divisor is greater than the 
            ' square root of n.
            If divisor * divisor > n Then
                exceedsSquareRoot = True
                ' Determine whether the divisor is a factor of n.
            ElseIf n Mod divisor = 0 Then
                firstDivisor = divisor
                foundDivisor = True
            End If
        End While
    
        Return Not foundDivisor
    
    End Function
    
    // This method tests n for primality against the list of 
    // prime numbers contained in the primes parameter.
    private bool IsPrime(
        ArrayList primes,
        int n,
        out int firstDivisor)
    {
        bool foundDivisor = false;
        bool exceedsSquareRoot = false;
    
        int i = 0;
        int divisor = 0;
        firstDivisor = 1;
    
        // Stop the search if:
        // there are no more primes in the list,
        // there is a divisor of n in the list, or
        // there is a prime that is larger than 
        // the square root of n.
        while (
            (i < primes.Count) &&
            !foundDivisor &&
            !exceedsSquareRoot)
        {
            // The divisor variable will be the smallest 
            // prime number not yet tried.
            divisor = (int)primes[i++];
    
            // Determine whether the divisor is greater
            // than the square root of n.
            if (divisor * divisor > n)
            {
                exceedsSquareRoot = true;
            }
            // Determine whether the divisor is a factor of n.
            else if (n % divisor == 0)
            {
                firstDivisor = divisor;
                foundDivisor = true;
            }
        }
    
        return !foundDivisor;
    }
    
  5. DeriveCalculatePrimeProgressChangedEventArgsمنProgressChangedEventArgs. Th هو الفئة هو اللازمة للإبلاغ عن نتائج المتزايد لمعالج الأحداث الخاص بالعميل ل ProgressChangedحدث. تحتوي خاصية مضافة واحدة تسمى LatestPrimeNumber.

    Public Class CalculatePrimeProgressChangedEventArgs
        Inherits ProgressChangedEventArgs
        Private latestPrimeNumberValue As Integer = 1
    
    
        Public Sub New( _
            ByVal latestPrime As Integer, _
            ByVal progressPercentage As Integer, _
            ByVal UserState As Object)
    
            MyBase.New(progressPercentage, UserState)
            Me.latestPrimeNumberValue = latestPrime
    
        End Sub
    
        Public ReadOnly Property LatestPrimeNumber() As Integer
            Get
                Return latestPrimeNumberValue
            End Get
        End Property
    End Class
    
    public class CalculatePrimeProgressChangedEventArgs :
            ProgressChangedEventArgs
    {
        private int latestPrimeNumberValue = 1;
    
        public CalculatePrimeProgressChangedEventArgs(
            int latestPrime,
            int progressPercentage,
            object userToken) : base( progressPercentage, userToken )
        {
            this.latestPrimeNumberValue = latestPrime;
        }
    
        public int LatestPrimeNumber
        {
            get
            {
                return latestPrimeNumberValue;
            }
        }
    }
    

Checkpoint (نقطة التحقق)

عند هذه النقطة، يمكنك بنية مكوّن.

إلى اختبار مكوّن الخاص بك

  • ترجمة مكوّن.

    كل يبقى المراد كتابتها هي وظائف لبدء وإلغاء غير متزامن العمليات، CalculatePrimeAsyncو CancelAsync.

تطبيق يبدأ وإلغاء وظائف

يبدأ العامل في أسلوب على مؤشر ترابط الخاص به بواسطة استدعاء BeginInvokeعلى المفوض الذي يلتف it. إلى إدارة عمر عملية غير متزامنة معين، يمكنك استدعاء CreateOperationالأسلوب تشغيل AsyncOperationManagerفئة. المساعد هذا ما يعيد AsyncOperation، الذي marshals مكالمات تشغيل معالجات حدث الخاصة بالعميل إلى مؤشر ترابط الصحيح أو سياق.

إلغاء الأمر معلّقة عملية معينة بواسطة استدعاء PostOperationCompletedفي المقابل له AsyncOperation. هذا بإنهاء هذه تشغيل أية مكالمات اللاحقة إلى به AsyncOperationسيتم طرح على ‏‏ استثناء.

إلى تنفيذ وظائف البدء 'و' إلغاء الأمر ':

  1. قم بتنفيذ الأسلوب CalculatePrimeAsync. تأكد من أن فريدة بالنسبة لكافة الرموز المميزة التي تمثل حاليا المعلقة مهام الرمز المميز المتوفر من قبل العميل (@). إذا مرت العميل في غير فريد الرمز مميز، CalculatePrimeAsyncيرفع على ‏‏ استثناء. وإلا، يتم تمت الإضافة الرمز المميز المعرف مهمة مجموعة.

    ' This method starts an asynchronous calculation. 
    ' First, it checks the supplied task ID for uniqueness.
    ' If taskId is unique, it creates a new WorkerEventHandler 
    ' and calls its BeginInvoke method to start the calculation.
    Public Overridable Sub CalculatePrimeAsync( _
        ByVal numberToTest As Integer, _
        ByVal taskId As Object)
    
        ' Create an AsyncOperation for taskId.
        Dim asyncOp As AsyncOperation = _
            AsyncOperationManager.CreateOperation(taskId)
    
        ' Multiple threads will access the task dictionary,
        ' so it must be locked to serialize access.
        SyncLock userStateToLifetime.SyncRoot
            If userStateToLifetime.Contains(taskId) Then
                Throw New ArgumentException( _
                    "Task ID parameter must be unique", _
                    "taskId")
            End If
    
            userStateToLifetime(taskId) = asyncOp
        End SyncLock
    
        ' Start the asynchronous operation.
        Dim workerDelegate As New WorkerEventHandler( _
            AddressOf CalculateWorker)
    
        workerDelegate.BeginInvoke( _
            numberToTest, _
            asyncOp, _
            Nothing, _
            Nothing)
    
    End Sub
    
    // This method starts an asynchronous calculation. 
    // First, it checks the supplied task ID for uniqueness.
    // If taskId is unique, it creates a new WorkerEventHandler 
    // and calls its BeginInvoke method to start the calculation.
    public virtual void CalculatePrimeAsync(
        int numberToTest,
        object taskId)
    {
        // Create an AsyncOperation for taskId.
        AsyncOperation asyncOp =
            AsyncOperationManager.CreateOperation(taskId);
    
        // Multiple threads will access the task dictionary,
        // so it must be locked to serialize access.
        lock (userStateToLifetime.SyncRoot)
        {
            if (userStateToLifetime.Contains(taskId))
            {
                throw new ArgumentException(
                    "Task ID parameter must be unique", 
                    "taskId");
            }
    
            userStateToLifetime[taskId] = asyncOp;
        }
    
        // Start the asynchronous operation.
        WorkerEventHandler workerDelegate = new WorkerEventHandler(CalculateWorker);
        workerDelegate.BeginInvoke(
            numberToTest,
            asyncOp,
            null,
            null);
    }
    
  2. قم بتنفيذ الأسلوب CancelAsync. إذا taskIdexهوts معلمة في المجموعة رموز، فإنه هو إزالة. يمنع هذا تم إلغاء المهام التي لم تبدأ من تشغيل. إذا كانت مهمة هو قيد التشغيل، BuildPrimeNumberListيخرج الأسلوب عند الكشف عن تمت إزالته المعرف مهمة من مجموعة مدة بقاء.

    ' This method cancels a pending asynchronous operation.
    Public Sub CancelAsync(ByVal taskId As Object)
    
        Dim obj As Object = userStateToLifetime(taskId)
        If (obj IsNot Nothing) Then
    
            SyncLock userStateToLifetime.SyncRoot
    
                userStateToLifetime.Remove(taskId)
    
            End SyncLock
    
        End If
    
    End Sub
    
    // This method cancels a pending asynchronous operation.
    public void CancelAsync(object taskId)
    {
        AsyncOperation asyncOp = userStateToLifetime[taskId] as AsyncOperation;
        if (asyncOp != null)
        {   
            lock (userStateToLifetime.SyncRoot)
            {
                userStateToLifetime.Remove(taskId);
            }
        }
    }
    

Checkpoint (نقطة التحقق)

عند هذه النقطة، يمكنك بنية مكوّن.

إلى اختبار مكوّن الخاص بك

  • ترجمة مكوّن.

PrimeNumberCalculator مكوّن الآن كاملة وجاهزة للاستخدام.

لعميل بريد مثال تستخدم PrimeNumberCalculatorالمكونات، راجع كيفية القيام بما يلي: تطبيق عميل من حدث يستند غير متزامن نقش.

الخطوات التالية

يمكنك تعبئة هذا مثال بكتابة CalculatePrime، ما متزامن CalculatePrimeAsyncالأسلوب. يؤدي هذا إلى جعل PrimeNumberCalculatorمكون الكامل متوافقاً مع يستند إلى حدث غير متزامن نقش.

You can improve this example by retaining the قائمة of all the prime numbers discovered by various invocations for different test numbers. قم باستخدام هذه الطريقة، سوف يستفيد كل مهمة من العمل المنجز بواسطة المهام السابقة. احرص على يحمي th هو lهوt مع lockالمناطق، حتى الوصول إلى lهوt واسطة عمليات جزئية المختلفة هو تسلسله.

يمكنك أيضا تحسين ذلك مثال باختبار ل divisors العادية، مثل 2 و 3 و 5.

راجع أيضًا:

المهام

كيفية القيام بما يلي: تشغيل عملية في الخلفية

كيفية القيام بما يلي: تنفيذ مكوّن التي تعتمد على النقش غير متزامن يستند إلى حدث

المبادئ

نظرة عامة تستند إلى حدث غير متزامن نقش حول

موارد أخرى

multithreading في Visual Basic

ذات مؤشرات ترابط متعددة البرمجة بالأحداث المستندة إلى نمط غير متزامن