Многопоточное взаимодействие приложений с потоком регистратора

Вы не должны жить с тем расширением, если можно установить фильтр ISAPI на сервере.

В основном Вы направляете подобранные URL к {контроллер} .mvc разнообразие, затем в ASP.NET, Вы переписываете этот URL для удаления .mvc - выполнение этого, Вы не должны определять дополнительные маршруты или представлять .mvc Вашим пользователям.

я записал об этом здесь: http://www.flux88.com/UsingASPNETMVCOnIIS6WithoutTheMVCExtension.aspx

и Steve Sanderson имеет хорошее сообщение здесь также: http://blog.codeville.net/2008/07/04/options-for-deploying-aspnet-mvc-to-iis-6/

6
задан XpiritO 20 February 2012 в 15:23
поделиться

4 ответа

Вроде должно работать. Производители-потребители не должны сильно меняться в случае единственного потребителя. Маленькие придирки:

  • получение блокировки может оказаться дорогостоящей операцией (как говорит @Vitaliy Lipchinsky). Я бы рекомендовал сравнить ваш регистратор с наивным "сквозным" регистратором и регистратором с использованием взаимосвязанных операций. Другой альтернативой может быть замена существующей очереди пустой в GetLog и немедленный выход из критического раздела. Таким образом, ни один из производителей не будет заблокирован длительными операциями с потребителями.

  • Сделайте LogObj ссылочным типом (классом). Нет смысла делать его структурированным, так как вы все равно его упаковываете. или иначе сделайте поле _queue типом LogObj [] (в любом случае это лучше).

  • сделайте фон вашего потока так, чтобы он не препятствовал закрытию вашей программы, если не будет вызвана Stop .

  • Очистите ваш TextWriter . В противном случае вы рискуете потерять даже те записи, которые уместились в очереди (10 элементов - это немного ИМХО).

  • Реализуйте IDisposable и / или финализатор. Вашему регистратору принадлежит поток и средство записи текста, и они должны быть освобождены (и очищены - см. Выше).

4
ответ дан 16 December 2019 в 21:42
поделиться

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

ПРИМЕЧАНИЕ: просто прочтите другие ответы. Далее следует довольно оптимальное, оптимистичное решение блокировки, основанное на вашем собственном. Основные отличия заключаются в блокировке внутреннего класса, минимизации «критических секций» и обеспечении плавного завершения потока. Если вы хотите полностью избежать блокировки, вы можете попробовать некоторые из этих непостоянных «неблокирующих» связанных списков, как предлагает @Vitaliy Lipchinsky.

using System.Collections.Generic;
using System.Linq;
using System.Threading;

...

public class Logger
{
    // BEST PRACTICE: private synchronization object. 
    // lock on _syncRoot - you should have one for each critical
    // section - to avoid locking on public 'this' instance
    private readonly object _syncRoot = new object ();

    // synchronization device for stopping our log thread.
    // initialized to unsignaled state - when set to signaled
    // we stop!
    private readonly AutoResetEvent _isStopping = 
        new AutoResetEvent (false);

    // use a Queue<>, cleaner and less error prone than
    // manipulating an array. btw, check your indexing
    // on your array queue, while starvation will not
    // occur in your full pass, ordering is not preserved
    private readonly Queue<LogObj> _queue = new Queue<LogObj>();

    ...

    public void Log (string message)
    {
        // you want to lock ONLY when absolutely necessary
        // which in this case is accessing the ONE resource
        // of _queue.
        lock (_syncRoot)
        {
            _queue.Enqueue (new LogObj (DateTime.Now, message));
        }
    }

    public void GetLog ()
    {
        // while not stopping
        // 
        // NOTE: _loggerThread is polling. to increase poll
        // interval, increase wait period. for a more event
        // driven approach, consider using another
        // AutoResetEvent at end of loop, and signal it
        // from Log() method above
        for (; !_isStopping.WaitOne(1); )
        {
            List<LogObj> logs = null;
            // again lock ONLY when you need to. because our log
            // operations may be time-intensive, we do not want
            // to block pessimistically. what we really want is 
            // to dequeue all available messages and release the
            // shared resource.
            lock (_syncRoot)
            {
                // copy messages for local scope processing!
                // 
                // NOTE: .Net3.5 extension method. if not available
                // logs = new List<LogObj> (_queue);
                logs = _queue.ToList ();
                // clear the queue for new messages
                _queue.Clear ();
                // release!
            }
            foreach (LogObj log in logs)
            {
                // do your thang
                ...
            }
        }
    }
}
...
public void Stop ()
{
    // graceful thread termination. give threads a chance!
    _isStopping.Set ();
    _loggerThread.Join (100);
    if (_loggerThread.IsAlive)
    {
        _loggerThread.Abort ();
    }
    _loggerThread = null;
}
3
ответ дан 16 December 2019 в 21:42
поделиться

Я просто провожу здесь мысленный эксперимент, так как у меня нет времени на самом деле сейчас попробовать код, но я думаю, что вы можете сделать это вообще без блокировок, если будете изобретательны.

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

Поскольку вы не пытаетесь вытолкнуть вещи из очереди до тех пор, пока семафор не будет установлен, и вы не устанавливая семафор до тех пор, пока вы не поместите вещи в очередь, я думаю это будет безопасно. Согласно документации MSDN для класса очереди, если вы перечисляете очередь, а другой поток изменяет коллекцию, возникает исключение. Поймайте это исключение, и все будет хорошо.

затем очередь удаляется, а семафор уменьшается.

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

затем очередь удаляется, а семафор уменьшается.

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

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

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

0
ответ дан 16 December 2019 в 21:42
поделиться

Фактически, вы вводите блокировку здесь. У вас есть блокировка при отправке записи журнала в очередь (метод журнала): если 10 потоков одновременно поместили 10 элементов в очередь и разбудили поток регистратора, то 11-й поток будет ждать, пока поток регистратора не зарегистрирует все элементы ...

Если вы хотите что-то действительно масштабируемое - реализуйте безблокировочную очередь (пример ниже). С механизмом синхронизации очереди без блокировки будет действительно сразу (вы даже можете использовать единственный дескриптор ожидания для уведомлений).

Если вам не удастся найти реализацию очереди без блокировки в Интернете, вот идея, как это сделать этот: Используйте связанный список для реализации. Каждый узел в связанном списке содержит значение и временную ссылку на следующий узел. поэтому для операций постановки в очередь и удаления из очереди вы можете использовать метод Interlocked.CompareExchange. Надеюсь, идея понятна. Если нет - дайте мне знать, и я предоставлю более подробную информацию.

1
ответ дан 16 December 2019 в 21:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: