На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> Одно и то же работает в Remoting и не работает в WCF , Странно :(
    Есть класс, реализующий функционал Remoting/WCF, в нём метод:

    ExpandedWrap disabled
              /// <summary>
              /// Подать команду серверу
              /// </summary>
              /// <param name="sCommand">Сериализованый объект команды</param>
              /// <returns>Сериализованный ответ</returns>
              public string SetCommand( string sCommand )
              {
                  // поместить команду в очередь ядра
                  MainFormServer.queueFromRemoting.Enqueue ( sCommand );
       
      //            File.AppendAllText("log.txt", "Command: " + sCommand + "\n enqueueed\n",
      //                Encoding.GetEncoding(1251));
       
                  // Ждать завершения
                  while ( MainFormServer.queueToRemoting.Count == 0 );
       
                  // вернуть клиенту ответ
                  return MainFormServer.queueToRemoting.Dequeue ( );
              }


    Что делает, думаю, понятно...
    В форме работает таймер, который мониторит queueFromRemoting (она public static) и отрабатывает команды.

    Это проработало в Remoting уже лет 5, всё как часы, идеально. И не на одной машине.
    Когда я переключился на WCF, метод вызывается (следил по логу - закомментаренная строчка), команда вроде проходит, но в очереди ничего не появляется (делал лог в таймере, длина очереди всегда ==0).
    При этом сервер виснет, жрёт проц по-полной (50% 2-х голового камня) :crazy: , а клиент отваливается где-то через минуту по таймауту :wacko: .
    Сервер, естественно, приходится вышибать руками через диспетчер задач.

    Исключений нигде не вылетает.
    В чём м.б. причина? Или к статическому объекту нельзя из WCF обращаться?

    Спасибо.
    Сообщение отредактировано: hd44780 -
      Мда ...

      Разобрался сам ... Спустя много дней :rolleyes: .
        Поделись?
          Делюсь :) .

          Зависон сервера и дикая загрузка проца связана были со строчкой

          // Ждать завершения
          while ( MainFormServer.queueToRemoting.Count == 0 );

          Таймер формы не видит команду и ничего не делает, в выходной очереди queueToRemoting ничего не появляется, соответственно цикл висит и вешает всё. В такие циклы надо что-то типа Thread.Sleep вставлять, либо таймаут делать, либо вообще менять идеологию опроса очереди.
          Но это так, мелкие сопутствующие проблемы ... Хоть и неправильно было изначально так делать. Но что сделано, то сделано ....

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

          ExpandedWrap disabled
              
                    /// <summary>
                    /// Подать команду серверу
                    /// </summary>
                    /// <param name="sCommand">Сериализованый объект команды</param>
                    /// <returns>Сериализованный ответ</returns>
                    public string SetCommand( string sCommand )
                    {
                        // Проверка объекта команды
                        if ( !CllCntCommand.CanDeserializeDoc ( sCommand ) )
                        { // ошибка
                            CllCntServerAnswer answ = new CllCntServerAnswer ( -1,  "ОШИБКА СЕРВЕРА: Неверная команда" );
                            answ.text = sCommand;
             
                            return answ.SerializeStr ( );
                        } // if
             
                        return (string)MainFormServer.mForm.Invoke(MainFormServer.mForm.commandDlg, sCommand);
                    } // SetCommand


          Куски из MainFormServer:

          В переменных формы
          ExpandedWrap disabled
                    /// <summary>
                    /// Ссылка на форму
                    /// </summary>
                    public static MainFormServer mForm;
             
                    /// <summary>
                    /// Тип делегата
                    /// </summary>
                    /// <param name="myString">Команда</param>
                    /// <returns>ОТвет на команду</returns>
                    public delegate string DoCommandDelegate(String myString);
             
                    /// <summary>
                    /// Делегат для подачи команды
                    /// </summary>
                    public DoCommandDelegate commandDlg;


          Это статическая ссылка на форму и делегат, обрабатывающий команды клиента.
          В событии загрузки формы инициализируем добро:
          ExpandedWrap disabled
                        // Делегат выполнения команд
                        mForm = this;
                        commandDlg = DoCommand;

          Может можно и в конструкторе, не знаю, не проверял, в загрузке мне кажется надёжнее... Типа объект формы уже полностью инициализирован и пр.

          Метод обрабатывающий команды:
          ExpandedWrap disabled
                    private string DoCommand(string sCommand)
                    {
                        return "Ответ на команду "+sCommand;
                    } // DoCommand


          Таймер и очереди я вообще убрал. Всё равно у меня 100% синхронная отработка команд.

          Так делать вообще правильнее, хотя я и по сей день не понимаю - почему старый вариант с таймером и очередями как часы работал в Remoting без единого сбоя, а в WCF вообще не работает :-? .
          Если кто мне объяснит сей "парадокс", буду благодарен.

          И почему в книгах про WCF даются только примитивные примеры для детского садика типа a+b/c, а действительно сложных вещей с подводными камнями (типа описанных выше) никто нигде не описывает?
          Нужели все думают, что 100% задач решаемы исключительно в рамках этого одного класса :wacko: примитивными методами вроде a+b/c?
          Сообщение отредактировано: hd44780 -
            Цитата
            while ( MainFormServer.queueToRemoting.Count == 0 );

            сама по-себе конструкция плохая. Будет много таких потоков, то ресурсов от процессора не останется. лучше использовать [Auto/Manual]ResetEvent.
            Или колбеки использовать, что лучше всего, в WCF есть такая возможность.
            Или уж тогда:

            ExpandedWrap disabled
              while ( MainFormServer.queueToRemoting.Count == 0 )
              {
                Thread.Sleep(1);
              }


            Но ручные слипы потоков - это очень плохо. Старайтесь избегать таких конструкций.

            Что касается вашего вопроса, то сложно сказать, есть предположение, что каждое обращение к переменной создавался пакет на хост ремотящего объекта MainFormServer, что выглядело примерно так:

            ExpandedWrap disabled
              int count = MainFormServer.RequestQueueCount();
              while ( count == 0 )
              {
                 count = MainFormServer.RequestQueueCount();
              }

            Поскольку RequestQueueCount вызов, то поток не жрал ресурсы, а честно выполнял инструкции и стоял на объектах синхронизации внутри ремотинга.

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

            Надо будет поиграться :)
            Сообщение отредактировано: maxim84_ -
              Спасибо, конечно, но уже всё это увы давно неактуально. Жизнь и судьба увели меня да-алеко от C# и .NET.
              А в виде хобби этим заниматься совершенно некогда.

              PS.
              Если честно, я даже не знаю, что такое SCRUM :yes-sad: ...
              Сообщение отредактировано: hd44780 -
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0431 ]   [ 17 queries used ]   [ Generated: 28.03.24, 11:45 GMT ]