// TODO: Add Error(Exception) override function to Task to support better error handling

        public override void Execute()
        {
            ItemScore itemScore = null;

            // Step 1: Score the Item
            try
            {
                // Note: This is sync but it is OK since it is executed by 1 of the thread pool threads so it is async to the original caller
                itemScore = scorerImpl.ScoreItem(studentResponse, null);
            }
            catch (Exception ex)
            {
                // Exception scoring item. Prepare an error report
                itemScore = new ItemScore(-1, -1, ScoringStatus.ScoringError, null,
                                          new ScoreRationale()
                {
                    Msg = "Exception scoring item " + studentResponse.ItemIdentifier + "\n" + ex.Message, Exception = ex
                },
                                          null, studentResponse.ContextToken);
            }

            // Step 2: Use the callback to report the score
            try
            {
                callback.ScoreAvailable(itemScore, studentResponse);
            }
            catch (Exception ex)
            {
                TDSLogger.Application.Error(new TraceLog("Item Scoring: Exception Reporting Score", ex));
            }
        }
        private ItemScore InvokeAsynchronousScoring(IItemScorer scorerImpl, ResponseInfo studentResponse, IItemScorerCallback callbackReference)
        {
            // if the scorer supports async mode then let the item scorer server deal with async
            if (scorerImpl.GetScorerInfo(studentResponse.ItemFormat).SupportsAsyncMode)
            {
                return(scorerImpl.ScoreItem(studentResponse, callbackReference));
            }

            // if the scorer does not handle async mode then we need to handle it in our own thread queue
            if (threadPool.Enqueue(new AsyncScoringTask(scorerImpl, studentResponse, callbackReference)))
            {
                return(new ItemScore(-1, -1, ScoringStatus.WaitingForMachineScore, null, null, null, studentResponse.ContextToken));
            }

            // if we get here then the thread queue is filled (probably waiting on a bunch of scores to come back)
            return(new ItemScore(-1, -1, ScoringStatus.WaitingForMachineScore, null, new ScoreRationale()
            {
                Msg = "Cannot enqueue scoring task"
            }, null, studentResponse.ContextToken));
        }
 private ItemScore InvokeSynchronousScoring(IItemScorer scorerImpl, ResponseInfo studentResponse)
 {
     return(scorerImpl.ScoreItem(studentResponse, null));
 }