C # - как обрабатывать дочерние потоки в приложении ASP.NET

Я создаю многопоточное приложение ASP.NET. Я новичок в написании многопоточных приложений. У меня есть основной класс, который порождает ряд потоков, которые запускаются во время использования приложения. Приложение имеет одну главную HTML-страницу. Когда страница HTML сначала открывается, она вызывает метод MyController.Start() для создания потоков и запуска их. Затем на странице HTML есть Javascript-процедура, которая постоянно проверяет страницу ASPX в моем приложении (каждые 2 секунды), чтобы получить данные и отобразить их. Существует основной класс, который я назвал «MyController», который является сердцем приложения. Он имеет локальную логическую переменную с именем Canceled, для которой установлено значение false. MyController порождает все дочерние потоки. Каждый дочерний поток имеет цикл, который продолжает выполняться до тех пор, пока Canceled = false. Один из потоков, который выполняется, используется в качестве монитора, чтобы убедиться, что страница HTML все еще работает и опроса. Если этот поток отмечает, что 30 секунд истекли с момента последнего опроса HTML-страницы, он меняет значение переменной Canceled на true. Затем один за другим все потоки заканчиваются и закрываются грациозно.

Мне нужно иметь возможность обрабатывать ситуацию, когда пользователь закрывает браузер, а затем снова открывает его до истечения 30 секунд. Я не чувствую, что полностью понимаю, что такое отношения между потоками, которые создаются и запускаются, и экземпляром MyController. Как только потоки создаются и запускаются, они просто запускаются независимо от чего-либо еще? У меня есть основной статический класс под названием «Приложение», который используется для обеспечения легкого доступа к контроллеру из любого места приложения. Как я его кодировал прямо сейчас, я думаю, что я создаю новые потоки каждый раз, когда загружается страница HTML. Поэтому, если пользователь должен закрыть страницу HTML, а затем снова открыть ее, я думаю, тогда у меня будет два экземпляра каждого потока. Это верно? Если да, то как я могу проверить, запущены ли эти потоки, чтобы я не создавал новые экземпляры?

Надеюсь, это имеет смысл! Заранее благодарю за любую помощь. Вот мой код.

Start.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
  if(App._myController == null)
  {
    App._myController = new MyController();
  }
  App._myController.Start();
}

Код библиотеки

public class App
{
  public static MyController _myController {get;set;}
  static App()
  {
    _myController = new MyController();
  }
}

public class MyController
{
  public bool Cancelled {get;set;}
  private object SyncLock = new object();
  Thread _thread1;
  Thread _thread2;
  Thread _thread3;

  public void Start()
  {
    this.Cancelled = false;
    _thread1 = new Thread(Worker1);
    _thread1.Start();

    _thread2 = new Thread(Worker2);
    _thread2.Start();

    _threadMonitor = new Thread(Monitor);
    _threadMonitor.Start();
  }

  public void Stop()
  {
    lock(this.SyncLock)
    {
      this.Cancelled = true;
    }
  }

  private void Worker1()
  {
    while(!Cancelled)
    {
      ..do some stuff..
    }
  }

  private void Worker2()
  {
    while(!Cancelled)
    {
      ..do some stuff..
    }
  }

  private void Monitor()
  {
    while(!Cancelled)
    {
      ..check database to see when last poll was
      ..if last poll is greater than 30 seconds ago
      {
        this.Stop();
      }
    }
  }

}
1
nl ja de
вы пробовали настроить свои потоки с помощью myThread.IsBackground = true; ?
добавлено автор AssaultingCuccos, источник
Дело с IsBackground установлено в true: если основной поток, где он выполняется при закрытии, то все фоновые потоки автоматически также прекращаются. Хотя я не уверен, что это будет работать на страницах asp.net, поэтому я не отправлял его в качестве ответа.
добавлено автор AssaultingCuccos, источник
Дело с IsBackground установлено в true: если основной поток, где он выполняется при закрытии, то все фоновые потоки автоматически также прекращаются. Хотя я не уверен, что это будет работать на страницах asp.net, поэтому я не отправлял его в качестве ответа.
добавлено автор AssaultingCuccos, источник
вы пробовали настроить свои потоки с помощью myThread.IsBackground = true; ?
добавлено автор AssaultingCuccos, источник
@FlorisPrijt - как настроить IsBackground = истинную помощь?
добавлено автор Corey Burnett, источник
@FlorisPrijt - как настроить IsBackground = истинную помощь?
добавлено автор Corey Burnett, источник
Позвольте мне сделать еще один важный комментарий. Это не «нормальное» приложение ASP.NET. Он строится для того, чтобы клиент работал на одном изолированном ноутбуке одним пользователем с IIS, работающим локально, отключенным от Интернета. Это не обычное многопользовательское приложение ASP.NET. Надеюсь, что это прояснит ситуацию.
добавлено автор Corey Burnett, источник
Позвольте мне сделать еще один важный комментарий. Это не «нормальное» приложение ASP.NET. Он строится для того, чтобы клиент работал на одном изолированном ноутбуке одним пользователем с IIS, работающим локально, отключенным от Интернета. Это не обычное многопользовательское приложение ASP.NET. Надеюсь, что это прояснит ситуацию.
добавлено автор Corey Burnett, источник

3 ответы

Я создаю многопоточное приложение ASP.NET. Я новичок в   написав многопоточные приложения. У меня есть основной класс, который порождает число   потоков, выполняемых во время использования приложения.

Noooo. Вы не должны этого делать. Нерест новой темы из ASP.NET - это справедливый способ застрелить себя ногой. Зачем? Поскольку каждый новый запрос обычно получает выделенный поток из пула потоков ASP.NET. Существует очень ограниченное количество потоков, которые вы можете получить (следовательно, количество логически параллельных запросов). Если запрос порождает другую ручную нить - происходят странные вещи, начиная с утечек памяти, взаимоблокировок и заканчивая сбоем вашего приложения или веб-сервера.

Как только запрос обрабатывается, ваш сервер должен полностью забыть о пользователе.

Вместо этого рассмотрите другой подход. Поддерживать состояние в:

  • База данных
  • Пользовательский файл cookie
  • скрытые скрытые поля
  • Контейнеры ASP.NET, которые сериализуются/десериализуются самим ASP.NET

Восстановите состояние по каждому новому запросу и сравните тайминги.

2
добавлено
@CoreyBurnett, что вы делаете, просит Windows Service поговорить с оборудованием и записать в базу данных. Страница ASP просто извлекала данные из базы данных по мере необходимости. Это более простое решение, что вы делаете, оно будет работать лучше и будет легче поддерживать.
добавлено автор Jon B, источник
@CoreyBurnett полностью согласен с Джоном
добавлено автор oleksii, источник
Если вы не находитесь вдалеке от текущего подхода, я бы попытался изменить его на дизайн без состояния и однопоточный подход (каждый новый запрос получает новый единственный поток). Легче писать, отлаживать и это известная простая модель, которая работает по всему миру в масштабе Интернета.
добавлено автор oleksii, источник
Ну, это не обычное приложение ASP.NET. Он будет работать на специальном ноутбуке и будет иметь только одного пользователя. Фактически, он даже не будет подключен к Интернету. В таких обстоятельствах вы все еще думаете, что это будет проблемой?
добавлено автор Corey Burnett, источник
ОК. Но у меня есть несколько параллельных процессов, которые нужно запускать одновременно. У меня есть 3 разных аппаратных средства, которые подключены к ноутбуку. Приложение должно иметь возможность общаться с этими вещами и извлекать данные из них через различные механизмы и в разное время. Основная страница HTML должна собирать все эти данные и отображать их. Сначала я думал о написании служб Windows, но вместо этого решил использовать многопоточный подход. Эти процессы необходимо запускать самостоятельно и разговаривать с различными аппаратными средствами.
добавлено автор Corey Burnett, источник
Это своего рода отображение в режиме реального времени для сбора данных с разных аппаратных средств. Существует основная база данных, которая используется как центральный репозиторий. Различные потоки общаются с различными аппаратными средствами и получают данные по разным графикам. Все они сохраняют его в базе данных. Затем основная HTML-страница просто запрашивает последние данные из базы данных и отображает ее. Я не уверен, как это сделать в приложении ASP.NET без использования потоков или нескольких служб Windows.
добавлено автор Corey Burnett, источник
Хм. Хорошо, спасибо за вход. Это очень помогло мне. К сожалению, я очень, очень далеко в развитии. Система работает хорошо и, похоже, не имеет утечек памяти. Но я понимаю, что вы говорите, и что служба Windows могла быть лучшим способом. Возможно, если мы построим версию 2, мы сможем перейти к службе Windows. Я очень ценю совет и за то, что вы тратите время на свой день, чтобы помочь!
добавлено автор Corey Burnett, источник

Я создаю многопоточное приложение ASP.NET. Я новичок в   написав многопоточные приложения. У меня есть основной класс, который порождает число   потоков, выполняемых во время использования приложения.

Noooo. Вы не должны этого делать. Нерест новой темы из ASP.NET - это справедливый способ застрелить себя ногой. Зачем? Поскольку каждый новый запрос обычно получает выделенный поток из пула потоков ASP.NET. Существует очень ограниченное количество потоков, которые вы можете получить (следовательно, количество логически параллельных запросов). Если запрос порождает другую ручную нить - происходят странные вещи, начиная с утечек памяти, взаимоблокировок и заканчивая сбоем вашего приложения или веб-сервера.

Как только запрос обрабатывается, ваш сервер должен полностью забыть о пользователе.

Вместо этого рассмотрите другой подход. Поддерживать состояние в:

  • База данных
  • Пользовательский файл cookie
  • скрытые скрытые поля
  • Контейнеры ASP.NET, которые сериализуются/десериализуются самим ASP.NET

Восстановите состояние по каждому новому запросу и сравните тайминги.

2
добавлено
@CoreyBurnett, что вы делаете, просит Windows Service поговорить с оборудованием и записать в базу данных. Страница ASP просто извлекала данные из базы данных по мере необходимости. Это более простое решение, что вы делаете, оно будет работать лучше и будет легче поддерживать.
добавлено автор Jon B, источник
@CoreyBurnett полностью согласен с Джоном
добавлено автор oleksii, источник
Если вы не находитесь вдалеке от текущего подхода, я бы попытался изменить его на дизайн без состояния и однопоточный подход (каждый новый запрос получает новый единственный поток). Легче писать, отлаживать и это известная простая модель, которая работает по всему миру в масштабе Интернета.
добавлено автор oleksii, источник
Ну, это не обычное приложение ASP.NET. Он будет работать на специальном ноутбуке и будет иметь только одного пользователя. Фактически, он даже не будет подключен к Интернету. В таких обстоятельствах вы все еще думаете, что это будет проблемой?
добавлено автор Corey Burnett, источник
ОК. Но у меня есть несколько параллельных процессов, которые нужно запускать одновременно. У меня есть 3 разных аппаратных средства, которые подключены к ноутбуку. Приложение должно иметь возможность общаться с этими вещами и извлекать данные из них через различные механизмы и в разное время. Основная страница HTML должна собирать все эти данные и отображать их. Сначала я думал о написании служб Windows, но вместо этого решил использовать многопоточный подход. Эти процессы необходимо запускать самостоятельно и разговаривать с различными аппаратными средствами.
добавлено автор Corey Burnett, источник
Это своего рода отображение в режиме реального времени для сбора данных с разных аппаратных средств. Существует основная база данных, которая используется как центральный репозиторий. Различные потоки общаются с различными аппаратными средствами и получают данные по разным графикам. Все они сохраняют его в базе данных. Затем основная HTML-страница просто запрашивает последние данные из базы данных и отображает ее. Я не уверен, как это сделать в приложении ASP.NET без использования потоков или нескольких служб Windows.
добавлено автор Corey Burnett, источник
Хм. Хорошо, спасибо за вход. Это очень помогло мне. К сожалению, я очень, очень далеко в развитии. Система работает хорошо и, похоже, не имеет утечек памяти. Но я понимаю, что вы говорите, и что служба Windows могла быть лучшим способом. Возможно, если мы построим версию 2, мы сможем перейти к службе Windows. Я очень ценю совет и за то, что вы тратите время на свой день, чтобы помочь!
добавлено автор Corey Burnett, источник

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

Из функции Start() , если потоки не равны null, установите для Canceled значение true и Join() потоков, затем продолжите существующей функциональности.

  public void Start()
  {
    this.Cancelled = true;

    if (_thread1 != null) _thread1.Join();
   //repeat for other threads

    this.Cancelled = false;
    _thread1 = new Thread(Worker1);
    _thread1.Start();

    _thread2 = new Thread(Worker2);
    _thread2.Start();

    _threadMonitor = new Thread(Monitor);
    _threadMonitor.Start();
  }

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

1
добавлено
@CoreyBurnett это будет только null в первый раз. Поскольку вы назначили это статической переменной, вы создаете этот класс только один раз.
добавлено автор Jon B, источник
Не будет ли _thread1 всегда иметь значение null при запуске Start? Или, потому что App._myController является статическим членом, _thread1 все равно будет ссылаться на поток, если вы запустите Start во второй раз?
добавлено автор Corey Burnett, источник
DotNetRuChat
DotNetRuChat
2 992 участник(ов)

Чат русскоязычного .NET сообщества http://dotnet.ru/ Вам могут быть интересны: @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @xamarin_russia, @microsoftstackjobs, @uwp_ru Флуд в @dotnettalks

Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

pro.net
pro.net
710 участник(ов)

Обсуждение .NET Framework и всего, что с ним связано. Правила: не флудить не по теме, уважать ваших коллег и никакой рекламы (объявления о вакансиях можно согласовать с @AlexFails). Флудилка: @dotnettalks Участник @proDOT

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

.NET Talks: Force Push Masters
.NET Talks: Force Push Masters
490 участник(ов)

Свободный чат .NET разработчиков. Правила: t.me/dotnettalks/56823 Вам могут быть интересны: @dotnetruchat, @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @dotnetgroup, @xamarin_russia, @microsoftstackjobs, @uwp_ru http://combot.org/chat/-1001128250813

.NET Chat Убежище
.NET Chat Убежище
246 участник(ов)

Чат .NET разработчиков под эгидой MSK/SPB .NET Community Group Вам могут быть интересны: @fsharp_chat, @dotnetruchat, @cilchat, @xamarin_russia, @microsoftstackjobs, @dotnetgroup Флуд в @dotnettalks

.NET CIL Chat
.NET CIL Chat
54 участник(ов)

.NET CIL (aka IL aka MSIL)