简体   繁体   中英

How to wait without freezing AND wait for the function to finish

I'd like to pause for a file update (can take a few seconds) using Thread.Sleep loop that checks every second for timestamp change. However, the app freezes completely during the sleep loop and can't even refresh the display.

I looked into the following (simplified) code which doesn't freeze the program. But the program reaches the end (prints "Done") before the Worker function ends - wait for the func to complete (print "end" before "done"). Unremarked the last line, to wait for the func's end, freezes the app.

Is there a better way to wait for file change without freezing the app? If not, how to wait for a lengthy function to complete without freezing the app AND waiting for the func to finish before commencing with the main code?

private static ManualResetEvent resetEvent = new ManualResetEvent(false);

private void Worker(object ignored)
{
    Print("start");
    Thread.Sleep(5000);
    Print("end")
    resetEvent.Set();
}

Main:
ThreadPool.QueueUserWorkItem(new WaitCallback(Worker));
Print("Done");
//resetEvent.WaitOne();

output with the last line remarked:

  1. Done
  2. start
  3. end

output with last line unremarked: (app freezes, then): 1. Start 2. End 3. Done

expected, without freezing:

  1. start
  2. end
  3. Done

As I mentioned in comments the right way would be to use async/await. The code will look like this:

private async Task Worker()
{
    Print("start");
    await Task.Delay(5000);
    Print("end");
}

main:

public async void DoSomething()
{
    await Worker();
    Print("Done");
}

If you want to use ThreadPool directly. Base on platform you may need to provide a Dispatcher to Worker method so it call a method to execute in initial thread.

I like waiting with Semaphores. Check out the overloaded method WaitOne.

using System;
using System.Threading;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Semaphore mutex = new Semaphore(0, 1);
            Thread t = new Thread(() => {
                Console.WriteLine("Hello from another thread");
                Console.ReadLine();
                mutex.Release();
            });
            t.Start();
            while (!mutex.WaitOne(1000))
                Console.WriteLine("Waiting " + 1 + " sec");
            Console.WriteLine("Hello from main thread");
            Console.ReadLine();
        }
    }
}

Assuming you are working with Winforms, one solution is this:

 class Foo
 {
   bool spin;
   void Worker()
   {      
       Print("start");
       ///Do job
       Print("end")

      spin=false;
   }
   void mainMethod()
   {    
        spin = true;
        ThreadPool.QueueUserWorkItem(new WaitCallback(Worker));
        while(spin)
        {
             Thread.Sleep(500);
             Application.DoEvents(); 
        }
   }
 }

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