Tanecik geliştirme

Bir grain sınıfı uygulamak için kod yazmadan önce .NET Standard veya .Net Core (tercih edilir) veya .NET Framework 4.6.1 veya daha yüksek bir (bağımlılıklar nedeniyle .NET Standard veya .NET Core kullanasanız) hedef alan yeni bir Sınıf Kitaplığı projesi oluşturun. Tanecik arabirimleri ve tanecik sınıfları aynı Sınıf Kitaplığı projesinde veya arabirimlerin uygulamadan daha iyi ayrılması için iki farklı projede tanımlanabilir. Her iki durumda da projelerin Microsoft.Core.Abstractions ve Microsoft.Windows.CodeGenerator.MSBuild NuGet gerekir.

Daha ayrıntılı yönergeler için Öğretici 1 – Project Temel Bilgiler'inKurulum bölümüne bakın.

Grain arabirimleri ve sınıfları

Tanecikler birbirleriyle etkileşime geçen ve ilgili tanecik arabirimlerinin bir parçası olarak bildirilen yöntemleri çağırarak dışarıdan çağrılır. Bir tanecik sınıfı, önceden bildirilen bir veya daha fazla tanecik arabirimleri ekler. Bir tanecik arabiriminin tüm yöntemleri bir Task (yöntemler void için), veya (ValueTask<TResult>Task<TResult> türünde değerleri döndüren yöntemler için) döndürerek bir döndürerek.T

Aşağıda, Komut sürümü 1.5 Varlık Hizmeti örneğinden bir alıntı ve bulunmaktadır:

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

Grain yöntemlerinden değer dönüş

türünde bir değer döndüren bir grain yöntemi, T bir grain arabiriminde döndüren olarak tanımlanır Task<T>. anahtar sözcüğüyle işaretlenen grain async yöntemleri için, dönüş değeri kullanılabilir olduğunda genellikle aşağıdaki deyim aracılığıyla döndürülür:

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

Değer döndüren bir tanecik yöntemi( etkili bir şekilde geçersiz yöntem) bir tanecik arabiriminde döndüren olarak tanımlanır Task. döndürülen, Task zaman uyumsuz yürütmeyi ve yönteminin tamamlanmasını gösterir. anahtar sözcüğüyle işaretlenen grain async yöntemleri için, bir "void" yöntemi yürütmeyi tamamlasa, özel değerinin değerinin dönmesi gerekir Task.CompletedTask:

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

olarak işaretlenen bir grain async yöntemi, değeri doğrudan döndürür:

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

Hiçbir void değer döndüren olarak async işaretlenen bir grain yöntemi yalnızca yürütmenin sonunda döndürür:

public async Task GrainMethod4()
{
    return;
}

Bir grain yöntemi başka bir zaman uyumsuz yöntem çağrısından bir tanecik veya değil dönüş değerini alırsa ve bu çağrının hata işleme işlemini gerçekleştirmesi gerek yoksa, Task yalnızca bu zaman uyumsuz çağrıdan aldığı değeri döndürür:

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

    return task;
}

Benzer şekilde, void bir tanecik yöntemi onu bekleyen Task başka bir çağrı tarafından döndürülen bir döndürülebilirsiniz.

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

ValueTask<T> yerine kullanılabilir Task<T>.

Tanecik başvurusu

Grain Reference, ilgili grain sınıfıyla aynı grain arabirimini uygulayan bir ara sunucu nesnesidir. Hedef tanecikin mantıksal kimliğini (tür ve benzersiz anahtar) kapsüller. Hedef tanecik için çağrı yapmak için bir tanecik başvurusu kullanılır. Her tane başvurusu tek bir taneye (tanecik sınıfının tek bir örneği) başvurur, ancak aynı taneye birden çok bağımsız başvuru oluşturabilir.

Bir tanecik başvurusu hedef tanecikin mantıksal kimliğini temsil ettiği için, tanenin fiziksel konumundan bağımsızdır ve sistemin tam bir yeniden başlatılmasından sonra bile geçerli kalır. Geliştiriciler diğer herhangi bir .NET nesnesi gibi tanecik başvurularını kullanabilir. Bir yönteme geçirilebilir, yöntem dönüş değeri olarak kullanılabilir, vb. ve hatta kalıcı depolama alanına kaydedilebilir.

Bir tanecik başvurusu, bir IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) tanenin kimliğini yöntemine aktararak elde edilir; Tkey burada, tanecik arabirimidir ve türün içindeki tanecikin benzersiz anahtarıdır.

Aşağıda yukarıda tanımlanan arabirimin bir tanecik başvurusu alma örnekleri IPlayerGrain verilmiştir.

Bir grain sınıfının içinden:

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

İstemci kodundan.

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

Grain yöntemi çağırma

Zaman uyumsuz programlama modeli , Zaman uyumsuz programlamaya dayalıdır. Önceki örnekte yer alan tanecik başvurularını kullanarak bir tanecik yöntemi çağrılma işlemi şu şekilde gerçekleştirebilirsiniz:

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

İki veya daha fazla birleştirme mümkündür Tasks; birleştirme Task işlemi, tüm oluşturanları tamamlandığında çözümlenen yeni bir Taskoluşturur. Bu, bir tanenin birden çok hesaplama başlatması ve devam etmeden önce hepsini tamamlaması için beklemesi gereken yararlı bir desendir. Örneğin, birçok bölümden oluşturulmuş bir web sayfası oluşturan bir ön uç parçası, her parça için bir tane olmak ve her sonuç için bir almak için birden çok arka Task uç çağrısı oluşturabilir. Daha sonra bu işlemlerin TasksTaskTasktamamlandıktan sonra bu birleştirmenin tamamlandıktan sonra tek tek veriler tamamlanmış olur ve web sayfasını biçimlendirmek için gereken tüm veriler alınmıştır.

Örnek:

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.

Sanal yöntemler

Bir grain sınıfı isteğe bağlı OnActivateAsyncOnDeactivateAsync olarak ve sanal yöntemleri geçersiz kilebilir; bunlar, sınıfın her bir tanesini etkinleştirme ve devre dışı bırakma işlemi sırasında Zaman çalışma zamanı tarafından çağrılır. Bu, tanecik koduna ek başlatma ve temizleme işlemleri gerçekleştirme fırsatı verir. tarafından bir özel durum, OnActivateAsync etkinleştirme işlemi başarısız olur. Geçersiz OnActivateAsynckılınmışsa, OnDeactivateAsync her zaman tanecik etkinleştirme işleminin bir parçası olarak çağrılır, ancak sunucu hatası veya başka anormal bir olay gibi her durumda çağrılma garantisi olmaz. Bu nedenle, uygulamaların durum değişikliklerinin kalıcılığı OnDeactivateAsync gibi kritik işlemleri gerçekleştirmek için güvenmesi gerekir. Bunu yalnızca en iyi çaba işlemleri için kullanmaları gerekir.