/// <summary> /// The actual internal folder scan implementation. /// </summary> private void InternalScan() { if (isDisposed) { return; } try { if (Interlocked.Increment(ref scanning) > 1) { return; // Don't allow multiple parallel scans } Dictionary <AppRef, AppPackageInfo> newPackages = new Dictionary <AppRef, AppPackageInfo>(); string[] files; files = Helper.GetFilesByPattern(packageFolder + "*.zip", SearchOption.TopDirectoryOnly); foreach (string file in files) { bool isRetry = false; retry: try { int size; using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read)) size = (int)fs.Length; using (AppPackage package = AppPackage.Open(file)) newPackages.Add(package.AppRef, new AppPackageInfo(package.AppRef, Path.GetFileName(file), file, package.MD5, size, File.GetLastWriteTimeUtc(file))); } catch (FileNotFoundException e) { SysLog.LogErrorStackDump("{0}", e.Message); } catch (DirectoryNotFoundException e) { SysLog.LogErrorStackDump("{0}", e.Message); } catch (IOException e) { // I've run into trouble where we've gotten notifications from the // file watcher while a new file is still locked for writing. In // this situation, I'm going to wait a bit and then retry the // operation once. if (!isRetry) { Thread.Sleep(RetryTime); isRetry = true; goto retry; } SysLog.LogErrorStackDump("{0}", e.Message); } catch (Exception e) { SysLog.LogErrorStackDump("Error [{0}] loading application package [{1}].", e.Message, file); } } // Determine if there have been any changes to the set of // application packages and then update the cached package set // and then raise the change event if there were any changes. bool changed = false; using (TimedLock.Lock(syncLock)) { foreach (var info in newPackages.Values) { if (!packages.ContainsKey(info.AppRef)) { changed = true; break; } else { var orgInfo = packages[info.AppRef]; if (info.FileName != orgInfo.FileName || !Helper.ArrayEquals(info.MD5, orgInfo.MD5)) { changed = true; break; } } } if (!changed) { foreach (AppPackageInfo info in packages.Values) { if (!newPackages.ContainsKey(info.AppRef)) { changed = true; break; } } } if (changed) { packages = newPackages; } } if (changed) { RaiseChangeEvent(); } } finally { Interlocked.Decrement(ref scanning); } }