How to wait correctly until BackgroundWorker completes?

前端 未结 10 1213
既然无缘
既然无缘 2020-12-02 11:19

Observe the following piece of code:

var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;         


        
10条回答
  •  难免孤独
    2020-12-02 11:53

    I was also looking for a suitable solution. I solved the waiting with an exclusive lock. The critical path in code are writing to a public container (here the console) and increasing or decreasing the workers. No thread should interfere while writing to this variable, otherwise the count is not guaranteed anymore.

    public class Program
    {
        public static int worker = 0;
        public static object lockObject = 0;
    
        static void Main(string[] args)
        {
    
            BackgroundworkerTest backgroundworkerTest = new BackgroundworkerTest();
            backgroundworkerTest.WalkDir("C:\\");
            while (backgroundworkerTest.Worker > 0)
            {
                // Exclusive write on console
                lock (backgroundworkerTest.ExclusiveLock)
                {
                    Console.CursorTop = 4; Console.CursorLeft = 1;
                    var consoleOut = string.Format("Worker busy count={0}", backgroundworkerTest.Worker);
                    Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth-consoleOut.Length));
                }
            }
        }
    }
    
    public class BackgroundworkerTest
    {
        private int worker = 0;
        public object ExclusiveLock = 0;
    
        public int Worker
        {
            get { return this.worker; }
        }
    
        public void WalkDir(string dir)
        {
            // Exclusive write on console
            lock (this.ExclusiveLock)
            {
                Console.CursorTop = 1; Console.CursorLeft = 1;
                var consoleOut = string.Format("Directory={0}", dir);
                Console.Write("{0}{1}", consoleOut, new string(' ', Console.WindowWidth*3 - consoleOut.Length));
            }
    
            var currentDir = new System.IO.DirectoryInfo(dir);
            DirectoryInfo[] directoryList = null;
            try
            {
                directoryList = currentDir.GetDirectories();
            }
            catch (UnauthorizedAccessException unauthorizedAccessException)
            {
                // No access to this directory, so let's leave
                return;
            }
    
            foreach (var directoryInfo in directoryList)
            {
                var bw = new BackgroundWorker();
    
                bw.RunWorkerCompleted += (sender, args) =>
                {
                    // Make sure that this worker variable is not messed up
                    lock (this.ExclusiveLock)
                    {
                        worker--;
                    }
                };
    
                DirectoryInfo info = directoryInfo;
                bw.DoWork += (sender, args) => this.WalkDir(info.FullName);
    
                lock (this.ExclusiveLock)
                {
                    // Make sure that this worker variable is not messed up
                    worker++;
                }
                bw.RunWorkerAsync();
            }
        }
    }
    

提交回复
热议问题