23

i'm creating asmx web service and have to create thread to do background IO to refresh system data. What is the right way? I'm not interested to get any results to creating thread. I just want the ASP.NET worker thread to create a thread that does it's loading and in the end makes one assign (I think assign _alldata = newData is atomic where both instances of my own big structure class SystemData) so the worker thread that created the the new thread can propagate instantly.

I read an article http://msdn.microsoft.com/fi-fi/magazine/cc164128%28en-us%29.aspx#S2 which suggest to use non-threadpool thread. The article however was about different / more complex scenario and didn't help me so much.

Thanks: Matti

PS. I have asked this question also in what is the right way to spawn thread for database IO in asmx web service? but that was too complex with multiple questions.

Community
  • 1
  • 1
char m
  • 7,840
  • 14
  • 68
  • 117

2 Answers2

31

Something like this:

public delegate void Worker();
private static Thread worker;

public static void Init(Worker work)
{
    worker = new Thread(new ThreadStart(work));
    worker.Start();
}

public static void Work()
{
    // do stuff
}

Then get things started by calling Init(Work).

If you call BeginInvoke() or ThreadPool.QueueUserWorkItem(), it uses an ASP.NET thread pool thread, which can impact the scalability of your application.

In case it's useful, I cover these issues in detail in my book, along with code examples, sample benchmarks, etc: Ultra-Fast ASP.NET.

RickNZ
  • 18,448
  • 3
  • 51
  • 66
  • Isn’t starting a new thread takes more resources then using a thread from the thread pool ? – SirMoreno Dec 01 '09 at 12:16
  • thanks for the answer! now there seems to be debate with you and SirMoreno whether to use thread pool thread or not... – char m Dec 01 '09 at 13:34
  • 1
    Yes, starting a new thread uses more resources than a threadpool thread. However, the idea is not to start a new thread for every action. Instead, start just one (or a small number) of your own threads, and then pass WorkItems of some kind to them for execution. Again, the problem with threadpool threads is that they will reduce the scalability of your app, because they are the same threads that are used to process the pages themselves. – RickNZ Dec 01 '09 at 13:52
  • thanks again Rick. think i'll go with non-threadpool thread. this is done every 24h. So not for every action ;) – char m Dec 01 '09 at 14:16
  • 2
    A problem with not using a thread-pool thread is that if app pool is recycled, and the non-threadpool thread is in middle of its work, it will be abruptly stopped, but if we use a thread pool thread then app pool recycle will allow the thread pool thread to run to completion. Thats i my understanding. RIGHT? – Sunil May 24 '13 at 00:53
  • Nice one.. I now finally understand what, how and when to use delegates.. :-) and of course the above code is working fine for me :) – choz Nov 15 '13 at 20:21
  • @RickNZ I have your book.(really covers the most important things). but regarding to your answer here : (assuming no exceptions or any problem occurs) - does a thread/task(background or not) is always guaranteed to be finished ? I asked [here](http://stackoverflow.com/questions/24361642/is-it-guaranteed-that-a-thread-will-complete-in-aspnet) a related question but didn't get an appropriate 100% answer. [from my testing]( http://i.stack.imgur.com/Y7ASv.jpg) - it is always working! isn't an ending request thread should end the tasks ??? – Royi Namir Jun 24 '14 at 06:11
  • @RoyiNamir barring certain types of exceptions or an AppPool exit/reset, foreground threads will always run to completion. If *all* foreground threads exit, then any remaining background threads are terminated. `ThreadPool` threads are background threads. "new Thread()" threads are foreground threads by default, or you can set `Thread.IsBackground`. ASP.NET request threads don't normally end after processing a request. Instead, they return to their thread pool, and from there can be immediately assigned to process another request, without ever ending. – RickNZ Jun 24 '14 at 10:14
  • If you do this and the code in Work() throws an exception, it will bring down the entire ASP.NET process with it. See http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx – d512 Jul 28 '15 at 00:51
5

Take a look at:

http://www.codeproject.com/KB/cs/AsyncMethodInvocation.aspx?fid=326357&df=90&mpp=25&noise=3&sort=Position&view=Quick

You can do something like:

 public delegate void MethodInvoker();

    private void Foo()
    {
        // sleep for 10 seconds.
        Thread.Sleep(10000);
    }

protected void Button2_Click(object sender, EventArgs e)
{
    // create a delegate of MethodInvoker poiting to
    // our Foo function.
    MethodInvoker simpleDelegate = new MethodInvoker(Foo);

    // Calling Foo Async
   simpleDelegate.BeginInvoke(null, null);

}
SirMoreno
  • 1,109
  • 1
  • 15
  • 34
  • thanks for the answer! now there seems to be debate with you and RickNZ whether to use thread pool thread or not... – char m Dec 01 '09 at 13:35
  • If the thread isn’t going to use a lot of CPU time (waiting for third party like DB) you better off using a custom thread pool: http://stackoverflow.com/questions/1031763/net-custom-threadpool-with-separate-instances Otherwise I think BeginInvoke is the right way. – SirMoreno Dec 01 '09 at 14:42