1

マルチスレッドのASP.NETアプリケーションを構築しています。マルチスレッドアプリを作成するのは初めてです。アプリケーションの使用中に実行される多数のスレッドを生成するメインクラスがあります。アプリケーションには1つのメインHTMLページがあります。HTMLページを最初に開くと、MyController.Start()メソッドを呼び出してスレッドを作成し、実行します。次に、HTMLページにはJavascriptルーチンがあり、アプリケーションのASPXページを継続的にポーリングして(2秒ごとに)データを取得して表示します。アプリケーションの心臓部である「MyController」と呼ばれるメインクラスがあります。これには、falseに設定されたCanceledというローカルブール変数があります。MyControllerは、すべての子スレッドを生成します。各子スレッドには、Canceled=falseである限り実行を継続するループがあります。実行中のスレッドの1つは、HTMLページがまだ稼働中でポーリングされていることを確認するためのモニターとして使用されます。このスレッドは、HTMLページが最後にポーリングされてから30秒が経過したことに気付いた場合、Canceled変数をtrueに変更します。次に、すべてのスレッドが1つずつ実行を終了し、正常に閉じます。

ユーザーがブラウザーを閉じてから、30秒が経過する前にブラウザーを再度開くという状況に対処できる必要があります。作成および開始されるスレッドとMyControllerのインスタンスとの関係を完全に理解しているとは思えません。スレッドが作成されて開始されると、他のスレッドとは独立して実行されますか?アプリケーションのどこからでもコントローラーに簡単にアクセスできるようにするために使用されるAppというメインの静的クラスがあります。現在のコーディング方法では、HTMLページが読み込まれるたびに新しいスレッドを作成していると思います。したがって、ユーザーがHTMLページを閉じてから再度開くと、すべてのスレッドの2つのインスタンスが実行されると思います。あれは正しいですか?もしそうなら、どうすればそれらのスレッドがすでに実行されているかどうかを確認して、実行していないかどうかを確認できます。

これが理にかなっていることを願っています!助けてくれてありがとう。これが私のコードです。

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();
      }
    }
  }

}
4

2 に答える 2

2

マルチスレッドのASP.NETアプリケーションを構築しています。マルチスレッドアプリを作成するのは初めてです。アプリケーションの使用中に実行される多数のスレッドを生成するメインクラスがあります。

Noooo。あなたはそれをすることになっていない。ASP.NETから新しいスレッドを生成することは、自分自身を足で撃つための公正な方法です。なんで?新しいリクエストは通常​​、ASP.NETスレッドプールから専用のスレッドを取得するためです。取得できるスレッドの数は非常に限られています(したがって、論理的に同時実行される要求の数)。リクエストによって別の手動スレッドが生成されると、メモリリーク、デッドロックから始まり、アプリケーションまたはWebサーバーがクラッシュするという奇妙なことが起こります。

リクエストが処理されると、サーバーはユーザーのことを完全に忘れるはずです。

代わりに、別のアプローチを検討してください。状態を維持する:

  • データベース
  • ユーザーCookie
  • HTMLの非表示フィールド
  • ASP.NET自体によってシリアル化/逆シリアル化されるASP.NETコンテナー

新しい各リクエストで状態を復元し、タイミングを比較します。

于 2013-01-09T16:06:35.267 に答える
1

私はあなたのデザインが好きではありませんが、それは別の質問です。私はあなたの現在のデザインであなたの現在の問題に対処します...

Start()関数から、スレッドがnullでない場合は、 Cancelledtrueに設定し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を使用して)ページとインターフェイスするバックグラウンド作業を行うサービスです。

于 2013-01-09T16:07:16.620 に答える