Является ли хорошей практикой блокировка потока, чтобы сделать транзакции в winforms? - PullRequest
0 голосов
/ 06 декабря 2011

Это старое школьное приложение winforms, с которым я работаю, и они использовали следующую схему проектирования:

Всякий раз, когда вам нужно сделать что-то транзакционным, операция выполняется в его собственном потоке, и поток блокируется (для каждой операции используется конкретный объект блокировки), а затем вызывается служба wcf, какая-то локальная объекты обновляются, затем блокировка снимается.

Это хорошая практика?

Ответы [ 4 ]

1 голос
/ 06 декабря 2011

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

0 голосов
/ 06 декабря 2011

Это не делает действие транзакционным. Я хотел бы принять это, чтобы означать, что либо вся операция выполнена успешно, либо она не имеет никакого эффекта - если я обновлю два локальных объекта внутри вашего блока синхронизации, ошибка со вторым не приведет к откату первого.

Кроме того, ничто не мешает основному потоку использовать два объекта во время их обновления - ему необходимо взаимодействовать, также блокируя.

Блокировка в фоновом потоке имеет смысл, только если вы также блокируете, когда используете эти объекты в основном потоке.

0 голосов
/ 06 декабря 2011

Пока вы не ожидаете несколько объектов блокировки, это должно быть хорошо. Тупик возникает, когда у вас такая ситуация:

Тема A:

lock (lockObject1)
{
    // Do some stuff

    lock (lockObject2)
    {
        // Do some stuff
    }
}

Резьба B:

lock (lockObject2)
{
    // Do some stuff

    lock (lockObject1)
    {
        // Do some stuff
    }
}

Если вам случится заблокировать lockObject1 в потоке A, а поток B заблокирует lockObject2 до того, как поток A заблокирует его, тогда оба потока будут ожидать объект, заблокированный в другом потоке, и ни один из них не будет разблокирован, поскольку каждый ожидает, пока объект заблокирован. Это упрощенный пример - есть много способов, которыми можно оказаться в этой ситуации.

Чтобы избежать тупика, не ждите второго объекта, пока у вас заблокирован первый объект. Если вы блокируете один объект за один раз, как это, вы не можете получить взаимоблокировку, потому что в конечном итоге поток блокировки освободит объект, который нужен ожидающему потоку. Так, например, вышеприведенное должно быть развернуто:

Тема A:

lock (lockObject1)
{
        // Do some stuff
}

lock (lockObject2)
{
        // Do some stuff
}

Резьба B:

lock (lockObject2)
{
        // Do some stuff
}

lock (lockObject1)
{
        // Do some stuff
}

В этом случае каждая операция блокировки будет завершена без попытки получения других ресурсов, и поэтому исключается взаимоблокировка.

0 голосов
/ 06 декабря 2011

Я не совсем понимаю, что вы имеете в виду, «заблокировать поток».Это что-то вроде этого?

static object ThreadLock = new object();

void ThreadProc(object state)
{
    lock (ThreadLock)
    {
        // do stuff here
    }
}

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

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