Megosztás a következőn keresztül:


Aszinkron tevékenységek létrehozása a WF-ben

AsyncCodeActivity a tevékenységszerzők számára egy alaposztályt biztosít, amely lehetővé teszi a származtatott tevékenységek számára az aszinkron végrehajtási logika implementálását. Ez olyan egyéni tevékenységekhez hasznos, amelyeknek aszinkron munkát kell végeznie a munkafolyamat-ütemező szál megtartása nélkül, és blokkolva azokat a tevékenységeket, amelyek párhuzamosan futtathatók. Ez a témakör áttekintést nyújt arról, hogyan hozhat létre egyéni aszinkron tevékenységeket a .AsyncCodeActivity

Az AsyncCodeActivity használata

System.Activities az egyéni tevékenységszerzőknek különböző alaposztályokat biztosítanak a különböző tevékenység-létrehozási követelményekhez. Mindegyik rendelkezik egy adott szemantika, és biztosít egy munkafolyamat-szerző (és a tevékenység futtatókörnyezet) egy megfelelő szerződést. A AsyncCodeActivity alapú tevékenység olyan tevékenység, amely a scheduler szálhoz képest aszinkron módon végez munkát, és amelynek végrehajtási logikája felügyelt kódban van kifejezve. Az aszinkron működés következtében a végrehajtás során tétlen AsyncCodeActivity pontot idézhet elő. Az aszinkron munka változékonysága miatt a AsyncCodeActivity tevékenység végrehajtásának időtartamára egy állandó blokk mindig létrejön. Ez megakadályozza, hogy a munkafolyamat-futtatókörnyezet az aszinkron munka közepén megőrizze a munkafolyamat-példányt, és megakadályozza, hogy a munkafolyamat-példány töröljön az aszinkron kód végrehajtása közben.

AsyncCodeActivity metódusok

A származtatott AsyncCodeActivity tevékenységek aszinkron végrehajtási logikát hozhatnak létre az BeginExecute egyéni kóddal felülbírált metódusok és EndExecute metódusok felülbírálásával. Amikor a futtatókörnyezet meghívja őket, ezek a metódusok átadnak egy AsyncCodeActivityContext. AsyncCodeActivityContextlehetővé teszi, hogy a tevékenység szerzője megosztott állapotot BeginExecute/ EndExecute biztosítson a környezet tulajdonságában.UserState Az alábbi példában egy GenerateRandom tevékenység véletlenszerű számot aszinkron módon hoz létre.

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);
    }
}

Az előző példatevékenység a következőből AsyncCodeActivity<TResult>származik, és egy emelt szintű OutArgument<int> névvel rendelkezik Result. A metódus által visszaadott értéket a GetRandom felülbírálás kinyeri EndExecute és visszaadja, és ezt az értéket értékként Result állítja be. Az aszinkron tevékenységeknek, amelyek nem adnak vissza eredményt, a következőből AsyncCodeActivitykell származnia: . Az alábbi példában egy DisplayRandom tevékenység van definiálva, amely a következőből AsyncCodeActivityszármazik: . Ez a tevékenység hasonló a GetRandom tevékenységhez, de az eredmény visszaadása helyett egy üzenetet jelenít meg a konzolon.

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: {0}", r.Next(1, 101));
    }
}

Vegye figyelembe, hogy mivel nincs visszatérési érték, DisplayRandom a meghatalmazott meghívásához használjon egy helyett egy ActionFunc<T,TResult> értéket, a meghatalmazott pedig nem ad vissza értéket.

AsyncCodeActivity felülbírálást Cancel is biztosít. EndExecute A BeginExecute szükséges felülbírálások nem kötelezőek, Cancel és felülbírálhatók, így a tevékenység törölheti a meglévő aszinkron állapotát a megszakítás vagy megszakítás során. Ha a törlés lehetséges és AsyncCodeActivity.ExecutingActivityInstance.IsCancellationRequested van true, a tevékenységnek hívnia MarkCanceledkell . Az ebből a módszerből eredő kivételek végzetesek a munkafolyamat-példány számára.

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();
    }
}

Aszinkron metódusok meghívása osztályon

A .NET-keretrendszer számos osztálya aszinkron funkciókat biztosít, és ez a funkció aszinkron módon hívható meg egy AsyncCodeActivity alapú tevékenység használatával. Az alábbi példában létrejön egy tevékenység, amely aszinkron módon hoz létre egy fájlt az FileStream osztály használatával.

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();
        }
    }
}

Megosztási állapot a BeginExecute és az EndExecute metódus között

Az előző példában BeginExecute a FileStream létrehozott objektum a EndExecute. Ez azért lehetséges, mert a file változó a következő tulajdonságban AsyncCodeActivityContext.UserStateBeginExecutelett átadva: . Ez a megfelelő módszer az állapot és a között BeginExecuteEndExecutevaló megosztáshoz. Helytelen egy tagváltozó használata a származtatott osztályban (FileWriter ebben az esetben) az állapot BeginExecute megosztásához, és EndExecute mivel a tevékenységobjektumra több tevékenységpéldány hivatkozhat. Ha egy tagváltozót próbál meg megosztani az állapoton, az azt eredményezheti, hogy az egyik ActivityInstance felülírja vagy egy másik ActivityInstanceértékeket használ fel.

Argumentumértékek elérése

Egy adott környezet AsyncCodeActivity a tevékenységen definiált argumentumokból áll. Ezek az argumentumok a paraméterrel érhetők el a BeginExecute/EndExecuteAsyncCodeActivityContext felülbírálásokból. Az argumentumok nem érhetők el a delegáltban, de az argumentumértékek vagy bármely más kívánt adat átadható a delegáltnak a paraméterek használatával. Az alábbi példában egy véletlenszerű számgenerálási tevékenység van definiálva, amely az argumentumból beolvasja a befogadó felső határt Max . Az argumentum értékét a rendszer átadja az aszinkron kódnak a meghatalmazott meghívásakor.

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);
    }
}

Műveletek vagy gyermektevékenységek ütemezése az AsyncCodeActivity használatával

AsyncCodeActivity A származtatott egyéni tevékenységek a munkafolyamat-szál esetében aszinkron módon hajtják végre a munkát, de nem biztosítják a gyermektevékenységek vagy műveletek ütemezését. Az aszinkron viselkedés azonban beépíthető a gyermektevékenységek összeállítással történő ütemezésébe. Létre lehet hozni egy aszinkron tevékenységet, majd egy Activity vagy NativeActivity több származtatott tevékenységből áll, hogy aszinkron viselkedést és ütemezést biztosítson a gyermektevékenységek vagy műveletek számára. Létrehozhat például egy olyan tevékenységet, amely az Activityaszinkron tevékenységet és a tevékenység logikáját implementáló egyéb tevékenységeket tartalmazza, és annak implementációjaként Sequence tartalmazza az aszinkron tevékenységet. További példák a tevékenységek írására a következővel ActivityNativeActivity: Tevékenység- és tevékenységkészítési beállítások létrehozása.

Lásd még