public void TestWrapperCollection() { WeightedTransaction<Transaction> transaction = new WeightedTransaction<Transaction>( Transaction.EndedDummy ); ObservedWeightedTransaction<Transaction> observed = new ObservedWeightedTransaction<Transaction>( transaction, endedCallback, progressUpdatedCallback ); WeightedTransactionWrapperCollection<Transaction> wrapper = new WeightedTransactionWrapperCollection<Transaction>( new ObservedWeightedTransaction<Transaction>[] { observed } ); Assert.AreSame(transaction, wrapper[0]); }
public void TestConstructorWithAlreadyEndedTransaction() { WeightedTransaction<Transaction> testTransaction = new WeightedTransaction<Transaction>( Transaction.EndedDummy ); IObservationSubscriber subscriber = this.mockery.NewMock<IObservationSubscriber>(); Expect.AtLeast(0).On(subscriber).Method("ProgressUpdated"); // This should no be called because otherwise, the 'Ended' event would be raised // to the transaction group before all transactions have been added into // the internal list, leading to an early ending or even multiple endings. Expect.Never.On(subscriber).Method("Ended"); using( ObservedWeightedTransaction<Transaction> test = new ObservedWeightedTransaction<Transaction>( testTransaction, new ObservedWeightedTransaction<Transaction>.ReportDelegate( subscriber.ProgressUpdated ), new ObservedWeightedTransaction<Transaction>.ReportDelegate( subscriber.Ended ) ) ) { this.mockery.VerifyAllExpectationsHaveBeenMet(); } }
/// <summary> /// Checks whether the provided transaction matches the comparison /// transaction of the instance /// </summary> /// <param name="other">Transaction to match to the comparison transaction</param> public bool Matches(ObservedWeightedTransaction<Transaction> other) { return ReferenceEquals(other.WeightedTransaction.Transaction, this.toMatch); }
public void TestConstructorWithEndingTransaction() { WeightedTransaction<Transaction> testTransaction = new WeightedTransaction<Transaction>( new FunkyTransaction() ); IObservationSubscriber subscriber = this.mockery.NewMock<IObservationSubscriber>(); Expect.AtLeast(0).On(subscriber).Method("ProgressUpdated"); Expect.Once.On(subscriber).Method("Ended"); using( ObservedWeightedTransaction<Transaction> test = new ObservedWeightedTransaction<Transaction>( testTransaction, new ObservedWeightedTransaction<Transaction>.ReportDelegate( subscriber.ProgressUpdated ), new ObservedWeightedTransaction<Transaction>.ReportDelegate( subscriber.Ended ) ) ) { this.mockery.VerifyAllExpectationsHaveBeenMet(); } }
/// <summary>Begins tracking the specified background transaction</summary> /// <param name="transaction">Background transaction to be tracked</param> /// <param name="weight">Weight to assign to this background transaction</param> public void Track(Transaction transaction, float weight) { // Add the new transaction into the tracking list. This has to be done // inside a lock to prevent issues with the progressUpdate callback, which could // access the totalWeight field before it has been updated to reflect the // new transaction added to the collection. lock(this.trackedTransactions) { bool wasEmpty = (this.trackedTransactions.Count == 0); if(transaction.Ended) { // If the ended transaction would become the only transaction in the list, // there's no sense in doing anything at all because it would have to be // thrown right out again. Only add the transaction when there are other // running transactions to properly sum total progress for consistency. if(!wasEmpty) { // Construct a new observation wrapper. This is done inside the lock // because as soon as we are subscribed to the events, we can potentially // receive them. The lock eliminates the risk of processing a progress update // before the transaction has been added to the tracked transactions list. this.trackedTransactions.Add( new ObservedWeightedTransaction<Transaction>( new WeightedTransaction<Transaction>(transaction, weight), this.asyncProgressUpdatedDelegate, this.asyncEndedDelegate ) ); } } else { // Not ended -- Transaction is still running // Construct a new transation observer and add the transaction to our // list of tracked transactions. ObservedWeightedTransaction<Transaction> observedTransaction = new ObservedWeightedTransaction<Transaction>( new WeightedTransaction<Transaction>(transaction, weight), this.asyncProgressUpdatedDelegate, this.asyncEndedDelegate ); this.trackedTransactions.Add(observedTransaction); // If this is the first transaction to be added to the list, tell our // owner that we're idle no longer! if(wasEmpty) { setIdle(false); } } // if transaction ended // This can be done after we registered the wrapper to our delegates because // any incoming progress updates will be stopped from the danger of a // division-by-zero from the potentially still zeroed totalWeight by the lock. this.totalWeight += weight; // All done, the total progress is different now, so force a recalculation and // send out the AsyncProgressUpdated event. recalculateProgress(); } // lock }