简体   繁体   中英

C# - how to handle child threads in ASP.NET application

I am building a multi-threaded ASP.NET application. I am new to writing multi-threaded apps. I have a main class that spawns a number of threads that run while the application is being used. The application has one main HTML page. When the HTML page is first opened it calls the MyController.Start() method to create the threads and get them running. Then the HTML page has a Javascript routine that continually polls an ASPX page in my application (every 2 seconds) to get data and display it. There is a main class I called "MyController" that is the heart of the application. It has a local boolean variable called Cancelled that is set to false. The MyController spawns all of the child threads. Each child thread has a loop that continues to execute as long as Cancelled = false. One of the threads that is running is used as a monitor to make sure that the HTML page is still up and polling. If this thread notices that 30 seconds have expired since the last time the HTML page polled then it changes the Cancelled variable to true. Then one by one all of the threads finish running and close gracefully.

I need to be able to handle the situation where the user closes the browser and then reopens it before the 30 seconds has expired. I don't feel like I completely understand what the relationship is between the threads that get created and started and the instance of MyController. Once threads are created and started do they just run independently of anything else? I have a main static class called App that is used to provide easy access to the controller from anywhere in the application. The way I have it coded right now I think that I am creating new threads every time that the HTML page is loaded. So if the user were to close the HTML page and then reopen it I think then I would have two instances of every thread running. Is that correct? If so, how can I check to see if those threads are already running so that I don't create new instances of them?

Hope this makes sense! Thanks in advance for any help. Here is my code.

Start.aspx.cs

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

Library code

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

}

I am building a multi-threaded ASP.NET application. I am new to writing multi-threaded apps. I have a main class that spawns a number of threads that run while the application is being used.

Noooo. You are not supposed to do that. Spawning a new thread from ASP.NET is a fair way to shoot yourself in a foot. Why? Because each new request generally gets a dedicated thread from ASP.NET thread pool. There is a very limited number of threads that you can get (hence number of logically concurrent requests). If a request spawns another manual thread - odd things will happen, starting from memory leaks, deadlocks and ending up crashing your application or web server.

Once a request is processed, your server should completely forget about the user.

Instead, consider different approach. Maintain state in:

  • Database
  • User cookie
  • Html hidden fields
  • ASP.NET containers that get serialized/deserialized by ASP.NET itself

Restore the state on new each request and compare the timings.

I'm not in love with your design, but that's a separate question. I'll address your current problem with your current design...

From your Start() function, if the threads are not null, set Cancelled to true and Join() the threads, then continue with your existing functionality.

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

As for a better approach, maybe a service to do the background work that would interface with your page using WCF (perhaps using REST).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM