Блокировка нескольких методов - PullRequest
0 голосов
/ 20 апреля 2020

у меня есть одноэлементный класс (MySingletonClass), который имеет три основных метода

  1. BeginTransaction (clientId)
  2. AddItem (item, clientId)
  3. CommitTransaction (clientId )

ClientClass:

public class ClientClass
{

    private string id;

    private MySingletonClass s = MySingletonClass.Instance;

    public ClientClass()
    {
      id = new Guid().ToString();
    }
    public void BeginTransaction()
    {
       //start a lock here
       s.BeginTransaction(id);
    }
    public void CommitTransaction()
    {
       s.CommitTransaction(id);
       //end lock here
    }
    public void AddItem(string item)
    {
       //no access until lock is released
       s.AddItem(item, id);
    }
}

Существует множество задач, каждая из которых со своим собственным классом ClientClass

Мне нужен способ сериализации доступа к singleton класс за транзакцией: если транзакция не была зафиксирована, то никакой другой поток не должен запускать новую транзакцию или вызывать какой-либо другой метод в экземпляре синглтона

Например, каждая задача может иметь такой код

Task.Factory.StartNew(() => 
{
   Client c = new ClientClass();
   c.BeginTransaction();
   c.AddItem("www");
   c.AddItem("qqq");
   c.CommitTransaction();
});

Task.Factory.StartNew(() => 
{
   Client c1 = new ClientClass();
   c1.BeginTransaction();
   c1.AddItem("aaa");
   c1.CommitTransaction();
});

Любая идея, как я могу архивировать это с какой-то блокировкой, которая запускается при начальной транзакции и освобождается при фиксации? Все примеры запуска монитора, мьютекса и блокировки, которые я видел, выпущены одним и тем же способом. Есть ли блокировка нескольких методов ??

1 Ответ

0 голосов
/ 20 апреля 2020

Ваш MySingletonClass может выглядеть примерно так:

public class MySingletonClass {
    private readonly Object _lockObject = new object();

    private List<string> _list = new List<string>();

    public void BeginTransaction()
    {
        Monitor.Enter(_lockObject);
        _list.Clear();
    }

    public void AddItem(string item)
    {
        if( Monitor.IsEntered(_lockObject) == false ) throw new ThreadStateException("Not owner of transaction");
        _list.Add(item);
    }

    public void CommitTransaction()
    {
        if( Monitor.IsEntered(_lockObject) == false ) throw new ThreadStateException("Not owner of transaction");
        Monitor.Exit(_lockObject);
    }

    public void RollbackTransaction()
    {
        if( Monitor.IsEntered(_lockObject) == false ) throw new ThreadStateException("Not owner of transaction");
        Monitor.Exit(_lockObject);
    }
}

Но если происходит сбой ClientClass (исключение выдается) между BeginTransaction и CommitTransaction, очень важно вызвать RollbackTransaction else все потоки заблокированы, так как монитор никогда не освобождается.

Так что это не рекомендуемое решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...