/// <exception cref="System.Exception"></exception>
		private void CheckConcurrencyMethod(AbstractDb4oTestCase toTest, string testMethodName
			)
		{
			MethodInfo checkMethod = CheckMethodFor(toTest.GetType(), testMethodName);
			if (null == checkMethod)
			{
				return;
			}
			// pass ExtObjectContainer as a param to check method
			IExtObjectContainer oc = Fixture().Db();
			try
			{
				checkMethod.Invoke(toTest, new object[] { oc });
			}
			finally
			{
				oc.Close();
			}
		}
		/// <exception cref="System.Exception"></exception>
		private void InvokeConcurrencyMethod(AbstractDb4oTestCase toTest, MethodInfo method
			)
		{
			Type[] parameters = Sharpen.Runtime.GetParameterTypes(method);
			bool hasSequenceParameter = false;
			if (parameters.Length == 2)
			{
				// ExtObjectContainer, seq
				hasSequenceParameter = true;
			}
			int threadCount = toTest.ThreadCount();
			threads = new Thread[threadCount];
			failures = new Exception[threadCount];
			for (int i = 0; i < threadCount; ++i)
			{
				threads[i] = new Thread(new ConcurrencyTestMethod.RunnableTestMethod(this, toTest
					, method, i, hasSequenceParameter), "ConcurrencyTestMethod.invokeConcurrencyMethod Thread["
					 + i + "]");
			}
			// start threads simultaneously
			for (int i = 0; i < threadCount; ++i)
			{
				threads[i].Start();
			}
			// wait for the threads to end
			for (int i = 0; i < threadCount; ++i)
			{
				threads[i].Join();
			}
			// check if any of the threads ended abnormally
			for (int i = 0; i < threadCount; ++i)
			{
				if (failures[i] != null)
				{
					// TODO: show all failures by throwing another kind of exception.
					throw failures[i];
				}
			}
			// check test result
			CheckConcurrencyMethod(toTest, method.Name);
		}
			internal RunnableTestMethod(ConcurrencyTestMethod _enclosing, AbstractDb4oTestCase
				 toTest, MethodInfo method, int seq, bool showSeq)
			{
				this._enclosing = _enclosing;
				this.toTest = toTest;
				this.method = method;
				this.seq = seq;
				this.showSeq = showSeq;
			}