The idea here is that we buffer all output and then once we are done - we signal the owner.
상속: ISpecificationRunListener, ISpecificationResultProvider
        private static ExitCode RunAssembly(Assembly assembly, RunOptions runOptions)
        {
            ISpecificationRunListener listener = new BufferedAssemblyTeamCityReporter(WriteToTeamCity);

            ISpecificationRunner specificationRunner = new AppDomainRunner(listener, runOptions);

            specificationRunner.RunAssembly(new AssemblyPath(assembly.Location));

            if (listener is ISpecificationResultProvider) {
                var errorProvider = (ISpecificationResultProvider) listener;
                if (errorProvider.FailureOccurred)
                    return ExitCode.Failure;
            }

            return ExitCode.Success;
        }
 // We need to buffer all output unfortunately, because unlike in the serial execution 
 // scenario we can end up in a sitution where whilst we are writing to the console another 
 // thread is also and the output gets interwinded. (For example happens with Fluent Migrator)
 //
 private static void WriteToTeamCity(BufferedAssemblyTeamCityReporter reporter)
 {
     lock (_outputLockObject) {
         _outputBuffer.Append(reporter.Buffer);
     }
 }