public void DetachedParentChild() { //Arrange var sequence = new BlockingCollection<int>(); var child1 = new Action(() => { sequence.Add(2); Thread.Sleep(5000); sequence.Add(4); }); var parent = new Action(() => { sequence.Add(1); Task.Factory.StartNew(child1); Thread.Sleep(2500); sequence.Add(3); }); //Act var parent_task = Task.Factory.StartNew(parent); parent_task.Wait(); //Assert Assert.IsTrue(Enumerable.SequenceEqual(new int[] { 1, 2, 3 }, sequence), sequence.Aggregate(new StringBuilder(), (whole, next) => whole.AppendFormat("{0}|", next)).ToString()); CollectionAssert.AreEqual(new int[] { 1, 2, 3 }, sequence.ToList()); }
/// <summary> /// Executes PhantomJS for a particular web site. /// </summary> /// <remarks> /// So, about the command-line parameters that are passed to PhantomJS... /// /// OMFG...escaping double-quotes as command-line params is a f*****g NIGHTMARE. Just do some /// googling and you'll be convinced. So if something includes a quote, this method will throw /// an exception. /// /// Apparently, the way to escape command line params depends in large part on the /// particular param parsing routine that is being used by the particular executable you are /// running. So a .net executable will be very different from something written in C++. /// Just for the hell of it, I tried doing a bunch of testing with a .net app to see if I could safely escape /// ANY input and I quickly gave up. So I thought that I'd just try and handle nothing /// but dubl-quotes... but even that was a ridiculous pile of horseshit. It's NOT what you would /// think - you can't just double up (like using "" for every literal double-quote) and slap /// double quotes around every param. That almost works - sometimes - but there are many cases where it doesn't. /// It's so inconsistent that it might as well be random. /// </remarks> /// <param name="pathToPhantomJSEXE">Path to the PhantomJS executable.</param> /// <param name="pathToJavascriptFile">The actual javascript file to send to PhantomJS for execution.</param> /// <param name="additionalArgs">Additional command line parameters to be sent to PhantomJS (and ultimately into your JS file).</param> /// <returns>The combined string output from both STDOUT and STDERR from the PhantomJS executable.</returns> public static object ExecutePhantomScript(string pathToPhantomJSEXE, string pathToJavascriptFile, params string[] additionalArgs) { if (additionalArgs != null && additionalArgs.Length > 0) { // Disallow parameters that have embedded double quotes. // See <remarks> node above in method comments. if (additionalArgs.Any(p => p.Contains("\""))) { throw new Exception("One or more parameters had embedded double-quotes; this is not allowed."); } } var output = new BlockingCollection <string>(); using (var p = new Process()) { // Put literal double quotes around each command line param var stringArgs = new StringBuilder().Append($"\"{pathToJavascriptFile}\""); if (additionalArgs != null) { foreach (var a in additionalArgs) { // Put literal double quotes around each command line param stringArgs.Append($" \"{a}\""); } } p.OutputDataReceived += (e, v) => output.Add($"stdout: {v.Data}"); p.ErrorDataReceived += (e, v) => output.Add($"stderr: {v.Data}"); p.StartInfo = new ProcessStartInfo { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, CreateNoWindow = true, Arguments = stringArgs.ToString(), FileName = pathToPhantomJSEXE }; p.Start(); p.BeginErrorReadLine(); p.BeginOutputReadLine(); p.WaitForExit(); } return(output.Aggregate(new StringBuilder(), (b, e) => b.Append($"{e}{Environment.NewLine}"), b => b.ToString())); }
public int ChangeGeoDataForFiles(IEnumerable<string> pathToImageFiles, string pathToTrack, int timezone, Action actionDuringIteration, out string errors) { errors = ""; if (pathToImageFiles.Count() == 0) return 0; IEnumerable<GeoData> track; try { using (var gpxeReader = new GpxFileReader(pathToTrack)) { track = gpxeReader.GetData(); } } catch (Exception e) { errors = String.Format(Resources.ErrorREadTrackFileUI, pathToTrack); m_Log.Error(String.Format(Resources.ErrorReadTrackFileLog, pathToTrack), e); return 0; } int countChangedFiles = 0; BlockingCollection<string> errosInProcces = new BlockingCollection<string>(); SynchronizationContext ctx = SynchronizationContext.Current; Parallel.ForEach(pathToImageFiles, file => { string error; var res = changeExifInformationInFile(file, createDirectoryForOutput(file), out error, (EXIFFileWorker photoExifInfo, out string er) => { er = ""; GeoData? geoData = new GeoDataWorker().GetGeoForPointByTime(photoExifInfo.GetDateTimeTaken().AddHours(-timezone), track); if (geoData == null) { er = String.Format(EXIFPhotoEditor.Properties.Resources.CantFindCoordsForPhotoUI, file); m_Log.ErrorFormat(EXIFPhotoEditor.Properties.Resources.CanTFindCoordsForPhotoLog, file); return false; } photoExifInfo.ChangeGeoData(geoData.Value.Latitude,geoData.Value.Longitude, geoData.Value.Altitude); return true; }); if (res) countChangedFiles++; else errosInProcces.Add(error); actionDuringIteration(); }); errors = errosInProcces.Aggregate("", (acum, str) => acum + str + "\r\n"); return countChangedFiles; }
/// <summary> /// Gets the agreement and tick. Return true if agreement was got and tick was success. /// </summary> public bool Tick() { var result = GetAgreement(); return(result && _limits.Aggregate(true, (current, limit) => current & limit.Tick())); }