C# multi-threaded console application - Console quits before threads complete

后端 未结 6 1131
感动是毒
感动是毒 2021-02-08 23:14

I have a c# console application that creates up to 5 threads.

The threads are executing fine, but the UI thread shuts down as it finishes its work.

Is there a

相关标签:
6条回答
  • 2021-02-08 23:44

    If you are using .NET 4.0:

    var tasks = new List<Task>();
    
    foreach(var url in urls)
    {
        tasks.Add(Task.Factory.StartNew(myMethod, url));
    }
    
    // do other stuff...
    
    // On shutdown, give yourself X number of seconds to wait for them to complete...
    Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));
    
    0 讨论(0)
  • 2021-02-08 23:59

    The threads in the ThreadPool are background threads and that means an exiting application won't wait for them to complete.

    You have a few options:

    • wait with for example a semaphore
    • wait on a counter with Sleep() , very crude but OK for a simple console app.
    • use the TPL, Parallel.ForEach(urls, url => MyMethod(url));
    0 讨论(0)
  • 2021-02-09 00:00

    Ah - the ThreadPool is background. It is queued, but then your program ends. Finished. Program terminates.

    Read up on Semaphores (WaitSignal) and wait- The threads in the callback at the end signal they are ended, when all have signaled that the main thread can continue.

    0 讨论(0)
  • 2021-02-09 00:02

    Simplest hack to fix your problem.

    In your program class:

    static volatile int ThreadsComplete = 0;
    

    In your "myMethod" at the end before return:

    //ThreadsComplete++; //*edit* for safety's sake
    Interlocked.Increment(ref ThreadsComplete);
    

    In your main method before it returns/ends:

    while(ThreadsComplete < urls.Count) { Thread.Sleep(10); }
    

    The above essentially hacks together a WaitForAll synchronization method.

    0 讨论(0)
  • 2021-02-09 00:02

    in Main:

    var m = new ManualResetEvent(false);
    // do something
    foreach (var url in urls)
    {
      Console.WriteLine("starting thread: " + url); 
      ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(myMethod), url);
    }
    m.WaitOne();
    
    
    private static void myMethod(object obj)
    {
      try{
       // do smt
      }
      finally {
        m.Set();
      }
    }
    
    0 讨论(0)
  • 2021-02-09 00:04

    If you're using .net 4 then:

    urls.AsParallel().ForAll(MyMethod);
    

    Prior to .net 4 then start individual threads, keep them in a list and call Join(). The fact the workers are not background would keep them alive after the main thread exited, but the Join() is more explicit.

            List<Thread> workers = new List<Thread>();
            foreach(var url in urls)
            {
                Thread t = new Thread(MyMethod) {IsBackground = false};
                workers.Add(t);
                t.Start(url);
            }
    
            foreach (var worker in workers)
            {
                worker.Join();
            }
    
    0 讨论(0)
提交回复
热议问题