Aracılığıyla paylaş


WF'de Zaman Uyumsuz Etkinlikler Oluşturma

AsyncCodeActivity etkinlik yazarlarına, türetilmiş etkinliklerin zaman uyumsuz yürütme mantığı uygulamasına olanak tanıyan bir temel sınıf sağlar. Bu, iş akışı planlayıcısının iş parçacığını meşgul etmeden ve paralel çalışabilecek etkinlikleri engellemeden, zaman uyumsuz işler yapmak zorunda olan özel etkinlikler için kullanışlıdır. Bu konu, AsyncCodeActivity kullanarak özel asenkron etkinliklerin nasıl oluşturulacağı hakkında genel bir bakış sağlar.

AsyncCodeActivity Kullanma

System.Activities , farklı etkinlik yazma gereksinimleri için farklı temel sınıflara sahip özel etkinlik yazarları sağlar. Her biri belirli bir anlamsal özellik taşır ve iş akışı yazarı ile etkinlik çalışma zamanına uygun bir sözleşme sunar. AsyncCodeActivity tabanlı bir etkinlik, zamanlayıcı iş parçacığına göre zaman uyumsuz işlev gören ve çalışma mantığı yönetilen kodda ifade edilen bir etkinliktir. Asenkron hale geldiğinde bir AsyncCodeActivity, yürütme sırasında bir boşta bekleme durumu oluşturabilir. Zaman uyumsuz çalışmanın geçici yapısı nedeniyle, AsyncCodeActivity etkinliğin yürütülmesi süresi boyunca her zaman kalıcı bir blok oluşturmaz. Bu, iş akışı çalışma zamanı ortamının, asenkron çalışmanın ortasında iş akışı örneğini kalıcı hale getirmesini ve ayrıca asenkron kod yürütülürken iş akışı örneğinin bellekten çıkarılmasını engeller.

AsyncCodeActivity Yöntemleri

'den AsyncCodeActivity türeyen etkinlikler, BeginExecute ve EndExecute yöntemlerini özel kodla geçersiz kılarak zaman uyumsuz yürütme mantığı oluşturabilir. Çalışma zamanı tarafından çağrıldığında, bu yöntemler bir AsyncCodeActivityContextgeçirilir. AsyncCodeActivityContext, etkinlik yazarının bağlam içindeki UserState özelliğinde paylaşılan durum sağlamak için BeginExecute/ EndExecute kullanmasına olanak tanır. Aşağıdaki örnekte, bir GenerateRandom etkinlik zaman uyumsuz olarak rastgele bir sayı oluşturur.

public sealed class GenerateRandom : AsyncCodeActivity<int>
{
    static Random r = new Random();

    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        // Create a delegate that references the method that implements
        // the asynchronous work. Assign the delegate to the UserState,
        // invoke the delegate, and return the resulting IAsyncResult.
        Func<int> GetRandomDelegate = new Func<int>(GetRandom);
        context.UserState = GetRandomDelegate;
        return GetRandomDelegate.BeginInvoke(callback, state);
    }

    protected override int EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        // Get the delegate from the UserState and call EndInvoke
        Func<int> GetRandomDelegate = (Func<int>)context.UserState;
        return (int)GetRandomDelegate.EndInvoke(result);
    }

    int GetRandom()
    {
        // This activity simulates taking a few moments
        // to generate the random number. This code runs
        // asynchronously with respect to the workflow thread.
        Thread.Sleep(5000);

        return r.Next(1, 101);
    }
}

** Önceki örnek etkinlik AsyncCodeActivity<TResult>'den türetilir ve Result adlı yükseltilmiş OutArgument<int> öğesine sahiptir. GetRandom yöntemi tarafından döndürülen değer, EndExecute geçersiz kılma işlemi tarafından ayıklanır ve döndürülür, ardından bu değer Result olarak ayarlanır. Zaman uyumsuz etkinliklerden sonuç döndürmeyenler AsyncCodeActivity türetilmelidir. Aşağıdaki örnekte, AsyncCodeActivity'den türetilen bir DisplayRandom etkinliği tanımlanmıştır. Bu etkinlik etkinlik gibidir GetRandom , ancak bir sonuç döndürmek yerine konsola bir ileti görüntüler.

public sealed class DisplayRandom : AsyncCodeActivity
{
    static Random r = new Random();

    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        // Create a delegate that references the method that implements
        // the asynchronous work. Assign the delegate to the UserState,
        // invoke the delegate, and return the resulting IAsyncResult.
        Action GetRandomDelegate = new Action(GetRandom);
        context.UserState = GetRandomDelegate;
        return GetRandomDelegate.BeginInvoke(callback, state);
    }

    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        // Get the delegate from the UserState and call EndInvoke
        Action GetRandomDelegate = (Action)context.UserState;
        GetRandomDelegate.EndInvoke(result);
    }

    void GetRandom()
    {
        // This activity simulates taking a few moments
        // to generate the random number. This code runs
        // asynchronously with respect to the workflow thread.
        Thread.Sleep(5000);

        Console.WriteLine($"Random Number: {r.Next(1, 101)}");
    }
}

Dönüş değeri olmadığından, DisplayRandom temsilcisini çağırmak için bir Func<T,TResult> yerine Action kullanır ve temsilci hiçbir değer döndürmez.

AsyncCodeActivity ayrıca bir Cancel geçersiz kılma seçeneği sunar. BeginExecute ve EndExecute gerekli geçersiz kılmalar olarak gereklidir, ancak Cancel isteğe bağlıdır ve iptal edildiğinde veya durdurulduğunda etkinliğin bekleyen asenkron durumunu temizleyebilmesi için yine de geçersiz kılınabilir. Temizleme mümkünse ve AsyncCodeActivity.ExecutingActivityInstance.IsCancellationRequestedtrue ise, etkinlik MarkCanceled çağrılmalıdır. Bu yöntemden fırlatılan her türlü özel durum iş akışı örneği için ölümcüldür.

protected override void Cancel(AsyncCodeActivityContext context)
{
    // Implement any cleanup as a result of the asynchronous work
    // being canceled, and then call MarkCanceled.
    if (context.IsCancellationRequested)
    {
        context.MarkCanceled();
    }
}

Bir Sınıfta Zaman Uyumsuz Yöntemleri Çağırma

.NET Framework'teki sınıfların çoğu eşzamansız işlevsellik sağlar ve bu işlevsellik, AsyncCodeActivity tabanlı bir etkinlik kullanılarak eşzamansız olarak çağrılabilir. Aşağıdaki örnekte, FileStream sınıfını kullanarak zaman uyumsuz olarak bir dosya oluşturan bir etkinlik oluşturulmaktadır.

public sealed class FileWriter : AsyncCodeActivity
{
    public FileWriter()
        : base()
    {
    }

    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        string tempFileName = Path.GetTempFileName();
        Console.WriteLine("Writing to file: " + tempFileName);

        FileStream file = File.Open(tempFileName, FileMode.Create);

        context.UserState = file;

        byte[] bytes = UnicodeEncoding.Unicode.GetBytes("123456789");
        return file.BeginWrite(bytes, 0, bytes.Length, callback, state);
    }

    protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        FileStream file = (FileStream)context.UserState;

        try
        {
            file.EndWrite(result);
            file.Flush();
        }
        finally
        {
            file.Close();
        }
    }
}

BeginExecute ve EndExecute Yöntemleri Arasında Paylaşım Durumu

Önceki örnekte, FileStream içinde BeginExecute oluşturulan nesnesine EndExecuteiçinde erişildi. Bu, BeginExecute içindeki AsyncCodeActivityContext.UserState özelliğine file değişkeni geçirildiğinden mümkündür. Bu, BeginExecute ve EndExecute arasında durum paylaşımı için doğru yöntemdir. BeginExecute ve EndExecute arasında durum paylaşmak için türetilmiş sınıfta (FileWriter bu örnekte) bir üye değişkeni kullanılması yanlıştır çünkü etkinlik nesnesine birden çok etkinlik örneği tarafından başvurulabilir. Durumu paylaşmak için bir üye değişkeni kullanmaya çalışmak, bir ActivityInstance değerin, üzerine yazılabilirlik veya farklı bir ActivityInstance değerin kullanılması ile sonuçlanmasına neden olabilir.

Argüman Değerlerine Erişme

ortamı AsyncCodeActivity , etkinlikte tanımlanan bağımsız değişkenlerden oluşur. Bu bağımsız değişkenlere AsyncCodeActivityContext parametresi kullanılarak BeginExecute/EndExecute geçersiz kılmalardan erişilebilir. Temsilcide bağımsız değişkenlere erişilemez, ancak bağımsız değişken değerleri veya istenen diğer veriler, parametreleri kullanılarak temsilciye geçirilebilir. Aşağıdaki örnekte, Max bağımsız değişkeninden dahil üst sınırı alan bir rastgele sayı oluşturma etkinliği tanımlanmıştır. Temsilci çağrıldığında bağımsız değişkenin değeri zaman uyumsuz koda geçirilir.

public sealed class GenerateRandomMax : AsyncCodeActivity<int>
{
    public InArgument<int> Max { get; set; }

    static Random r = new Random();

    protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
    {
        // Create a delegate that references the method that implements
        // the asynchronous work. Assign the delegate to the UserState,
        // invoke the delegate, and return the resulting IAsyncResult.
        Func<int, int> GetRandomDelegate = new Func<int, int>(GetRandom);
        context.UserState = GetRandomDelegate;
        return GetRandomDelegate.BeginInvoke(Max.Get(context), callback, state);
    }

    protected override int EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
    {
        // Get the delegate from the UserState and call EndInvoke
        Func<int, int> GetRandomDelegate = (Func<int, int>)context.UserState;
        return (int)GetRandomDelegate.EndInvoke(result);
    }

    int GetRandom(int max)
    {
        // This activity simulates taking a few moments
        // to generate the random number. This code runs
        // asynchronously with respect to the workflow thread.
        Thread.Sleep(5000);

        return r.Next(1, max + 1);
    }
}

AsyncCodeActivity Kullanarak Eylemleri veya Alt Etkinlikleri Zamanlama

AsyncCodeActivity türetilmiş özel etkinlikler, iş akışı iş parçacığıyla ilgili olarak işi zaman uyumsuz olarak gerçekleştirmek için bir yöntem sağlar, ancak alt etkinlikleri veya eylemleri zamanlama olanağı sağlamaz. Ancak, asenkron davranışlar, bileşime dayalı olarak alt etkinliklerin zamanlanmasıyla entegre edilebilir. Zaman uyumsuz bir etkinlik oluşturulabilir ve ardından zaman uyumsuz davranış ve alt etkinliklerin veya eylemlerin zamanlamasını sağlamak için bir Activity veya NativeActivity türetilmiş etkinlikle oluşturulabilir. Örneğin, Activity'dan türetilen ve uygulama olarak zaman uyumsuz etkinliği içeren, ayrıca etkinliğin mantığını uygulayan diğer etkinlikleri barındıran bir Sequence etkinlik oluşturulabilir. Activity ve NativeActivity kullanarak etkinlik oluşturma hakkında daha fazla örnek için bkz Nasıl yapılır: Etkinlik oluşturma ve Etkinlik Yazma Seçenekleri.

Ayrıca bkz.