Bagikan melalui


Mengembangkan biji-bijian

Sebelum Anda menulis kode untuk mengimplementasikan kelas butir, buat proyek Perpustakaan Kelas baru yang menargetkan .NET Standard atau .Net Core (preferred) atau .NET Framework 4.6.1 atau lebih tinggi (jika Anda tidak dapat menggunakan .NET Standard atau .NET Core karena dependensi). Antarmuka biji-bijian dan kelas biji-bijian dapat didefinisikan dalam proyek Perpustakaan Kelas yang sama, atau dalam dua proyek yang berbeda untuk pemisahan antarmuka yang lebih baik dari implementasi. Dalam kedua kasus, proyek perlu mereferensikan paket Microsoft.Orleans.Core.Abstractions dan Microsoft.Orleans.CodeGenerator.MSBuild NuGet.

Untuk instruksi yang lebih menyeluruh, lihat bagian Pengaturan Project dari Tutorial Satu – Dasar-Dasar Orleans.

Antarmuka dan kelas grain

Biji-bijian berinteraksi satu sama lain dan dipanggil dari luar dengan metode pemanggilan yang dinyatakan sebagai bagian dari antarmuka biji-bijian masing-masing. Kelas biji-bijian mengimplementasikan satu atau lebih antarmuka biji-bijian yang dinyatakan sebelumnya. Semua metode antarmuka biji-bijian harus mengembalikan a Task (untuk void metode), a Task<TResult> atau a ValueTask<TResult> (untuk metode mengembalikan nilai tipe T).

Berikut ini adalah kutipan dari sampel Orleans versi 1.5 Presence Service:

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();
    Task JoinGame(IGameGrain game);
    Task LeaveGame(IGameGrain game);
}

public class PlayerGrain : Grain, IPlayerGrain
{
    private IGameGrain _currentGame;

    // Game the player is currently in. May be null.
    public Task<IGameGrain> GetCurrentGame()
    {
       return Task.FromResult(_currentGame);
    }

    // Game grain calls this method to notify that the player has joined the game.
    public Task JoinGame(IGameGrain game)
    {
       _currentGame = game;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} joined game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
    }

   // Game grain calls this method to notify that the player has left the game.
   public Task LeaveGame(IGameGrain game)
   {
       _currentGame = null;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} left game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
   }
}

Mengembalikan nilai dari metode butir

Metode butir yang mengembalikan nilai jenis T didefinisikan dalam antarmuka butir sebagai mengembalikan Task<T>. Untuk metode butir yang tidak ditandai dengan async kata kunci, ketika nilai pengembalian tersedia, biasanya dikembalikan melalui pernyataan berikut:

public Task<SomeType> GrainMethod1()
{
    return Task.FromResult(GetSomeType());
}

Metode butir yang tidak mengembalikan nilai, secara efektif metode void, didefinisikan dalam antarmuka butir sebagai mengembalikan Task. Yang dikembalikan Task menunjukkan eksekusi asinkron dan penyelesaian metode. Untuk metode butir yang tidak ditandai dengan async kata kunci, ketika metode "void" menyelesaikan eksekusinya, ia perlu mengembalikan nilai Task.CompletedTaskkhusus:

public Task GrainMethod2()
{
    return Task.CompletedTask;
}

Metode butir yang ditandai sebagai async mengembalikan nilai secara langsung:

public async Task<SomeType> GrainMethod3()
{
    return await GetSomeTypeAsync();
}

Metode butir yang void ditandai sebagai async yang tidak mengembalikan nilai hanya kembali pada akhir eksekusinya:

public async Task GrainMethod4()
{
    return;
}

Jika metode butir menerima nilai pengembalian dari panggilan metode asinkron lain, ke butir atau tidak, dan tidak perlu melakukan penanganan kesalahan panggilan itu, itu cukup mengembalikan Task yang diterimanya dari panggilan asinkron itu:

public Task<SomeType> GrainMethod5()
{
    Task<SomeType> task = CallToAnotherGrain();

    return task;
}

Demikian pula, void metode biji-bijian dapat mengembalikan Task kembali ke sana dengan panggilan lain alih-alih menunggunya.

public Task GrainMethod6()
{
    Task task = CallToAsyncAPI();
    return task;
}

ValueTask<T> dapat digunakan sebagai pengganti Task<T>.

Referensi butir

Referensi Biji-bijian adalah objek proxy yang mengimplementasikan antarmuka butir yang sama dengan kelas butir yang sesuai. Ini merangkum identitas logis (jenis dan kunci unik) dari biji-bijian target. Referensi biji-bijian digunakan untuk melakukan panggilan ke biji-bijian target. Setiap referensi biji-bijian adalah untuk satu butir (satu contoh dari kelas biji-bijian), tetapi seseorang dapat membuat beberapa referensi independen untuk biji-bijian yang sama.

Karena referensi biji-bijian mewakili identitas logis dari biji-bijian target, itu tidak tergantung pada lokasi fisik biji-bijian, dan tetap berlaku bahkan setelah restart lengkap sistem. Pengembang dapat menggunakan referensi butir seperti objek .NET lainnya. Ini dapat diteruskan ke metode, digunakan sebagai nilai pengembalian metode, dll., Dan bahkan disimpan ke penyimpanan persisten.

Referensi biji-bijian dapat diperoleh dengan meneruskan identitas biji-bijian ke IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) metode, di mana T antarmuka biji-bijian dan key merupakan kunci unik dari biji-bijian dalam jenis.

Berikut ini adalah contoh bagaimana mendapatkan referensi biji-bijian dari antarmuka yang IPlayerGrain didefinisikan di atas.

Dari dalam kelas biji-bijian:

IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Dari kode klien Orleans.

IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

Pemanggilan metode butir

Model pemrograman Orleans didasarkan pada pemrograman asinkron. Menggunakan referensi biji-bijian dari contoh sebelumnya, berikut adalah cara melakukan pemanggilan metode biji-bijian:

// Invoking a grain method asynchronously
Task joinGameTask = player.JoinGame(this);

// The await keyword effectively makes the remainder of the
// method execute asynchronously at a later point
// (upon completion of the Task being awaited) without blocking the thread.
await joinGameTask;

// The next line will execute later, after joinGameTask has completed.
players.Add(playerId);

Dimungkinkan untuk bergabung dengan dua atau lebih Tasks; operasi gabungan menciptakan yang baru Task yang diselesaikan ketika semua konstituennya Taskselesai. Ini adalah pola yang berguna ketika biji-bijian perlu memulai beberapa perhitungan dan menunggu semuanya selesai sebelum melanjutkan. Misalnya, butir front-end yang menghasilkan halaman web yang terbuat dari banyak bagian dapat membuat beberapa panggilan back-end, satu untuk setiap bagian, dan menerima Task untuk setiap hasil. Butir kemudian akan menunggu bergabung dari semua ini Tasks; ketika bergabung Task diselesaikan, individu Tasktelah selesai, dan semua data yang diperlukan untuk memformat halaman web telah diterima.

Contoh:

List<Task> tasks = new List<Task>();
Message notification = CreateNewMessage(text);

foreach (ISubscriber subscriber in subscribers)
{
    tasks.Add(subscriber.Notify(notification));
}

// WhenAll joins a collection of tasks, and returns a joined
// Task that will be resolved when all of the individual notification Tasks are resolved.
Task joinedTask = Task.WhenAll(tasks);

await joinedTask;

// Execution of the rest of the method will continue
// asynchronously after joinedTask is resolve.

Metode virtual

Kelas butir dapat secara opsional menimpa OnActivateAsync dan OnDeactivateAsync metode virtual; ini dipanggil oleh runtime Orleans pada saat aktivasi dan penonaktifan setiap butir kelas. Ini memberi kode butir kesempatan untuk melakukan operasi inisialisasi dan pembersihan tambahan. Pengecualian yang dilemparkan oleh OnActivateAsync kegagalan proses aktivasi. Sementara OnActivateAsync, jika diganti, selalu disebut sebagai bagian dari proses aktivasi biji-bijian, OnDeactivateAsync tidak dijamin untuk dipanggil dalam semua situasi, misalnya, jika terjadi kegagalan server atau peristiwa abnormal lainnya. Karena itu, aplikasi tidak boleh diandalkan OnDeactivateAsync untuk melakukan operasi kritis seperti kegigihan perubahan negara. Mereka harus menggunakannya hanya untuk operasi upaya terbaik.