de la tâche.Attendre la levée d'une exception

En grande partie à la suite de cette question le test driven asynch tâches je viens avec un peu de code qui fonctionne si je n'ai pas la tâche attendre, mais échoue si je n'.

Quelqu'un peut-il expliquer pourquoi?

Exception:

J'ai cette erreur lorsque le code frappe le constructeur d'une classe utilitaire écrit par Stephen Cleary sur son blog ici

public ProgressReporter()
{
    _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
}

Test 'Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.OnSuccessFullComplete_ExpectedResultIsReturned_JustWait' failed:
System.AggregateException : One or more errors occurred.
----> System.InvalidOperationException : The current SynchronizationContext may not be used as a TaskScheduler.
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
Threading\ProgressReporterTests.cs(142,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.OnSuccessFullComplete_ExpectedResultIsReturned_JustWait()
--InvalidOperationException
at System.Threading.Tasks.SynchronizationContextTaskScheduler..ctor()
at System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext()
Threading\ProgressReporter.cs(24,0): at Smack.Core.Lib.Threading.ProgressReporter..ctor()
Threading\ProgressReporterTests.cs(52,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests._startBackgroundTask(Boolean causeError)
Threading\ProgressReporterTests.cs(141,0): at Smack.Core.Presentation.Tests.Threading.ProgressReporterTests.<OnSuccessFullComplete_ExpectedResultIsReturned_JustWait>b__a()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()

Le test (NUnit w/TestDriven.Net coureur):

private class MockSynchContext : SynchronizationContext{}

[Test]
public void OnSuccessFullComplete_ExpectedResultIsReturned_Wait()
{
    var mc = new MockSynchContext();
    SynchronizationContext.SetSynchronizationContext(mc);
    Assert.That(SynchronizationContext.Current, Is.EqualTo(mc));
    Assert.DoesNotThrow(() => TaskScheduler.FromCurrentSynchronizationContext());
    var task = Task.Factory.StartNew(() => _startBackgroundTask(false));
    task.Wait(2000);
    _actualResult = 42;
}

Le SuT:

private void _startBackgroundTask(bool causeError)
{
    _cancellationTokenSource = new CancellationTokenSource();
    var cancellationToken = _cancellationTokenSource.Token;
    _progressReporter = new ProgressReporter();
    var task = Task.Factory.StartNew(() =>
            {
                for (var i = 0; i != 100; ++i) {
                    //Check for cancellation 
                    cancellationToken.ThrowIfCancellationRequested();

                    Thread.Sleep(30); //Do some work. 

                    //Report progress of the work. 
                    _progressReporter.ReportProgress(
                        () =>
                            {
                                //Note: code passed to "ReportProgress" can access UI elements freely. 
                                _currentProgress = i;
                            });
                }

                //After all that work, cause the error if requested.
                if (causeError) {
                    throw new InvalidOperationException("Oops...");
                }


                //The answer, at last! 
                return 42;
            },
        cancellationToken);

    //ProgressReporter can be used to report successful completion,
    // cancelation, or failure to the UI thread. 
    _progressReporter.RegisterContinuation(task, () =>
    {
        //Update UI to reflect completion.
        _currentProgress = 100;

        //Display results.
        if (task.Exception != null)
            _actualErrorMessage = task.Exception.ToString();
        else if (task.IsCanceled)
            _wasCancelled = true;
        else 
            _actualResult = task.Result;

        //Reset UI.
        _whenCompleted();
    });
}

Juste pour être clair: Si j'en commentaire de la tâche.Attendez, ce test réussit. Pourquoi est-ce?

Des points supplémentaires:

Je sais que c'est techniquement une autre question, mais il semble dommage de répéter tout cela, donc:

Pourquoi mon MockSynchContext pas lever une exception sur TaskScheduler.FromCurrentSynchronizationContext() dans mon test, mais n'a dans la deuxième tâche? Plus important encore, est-il un moyen de passer le contexte le long afin que je puisse faire le test correctement?

Cleary: Peut-être que vous devriez demander à Stephen. 😉 Je suis curieux de savoir si l' @alias fonctionnalité fonctionne sur les postes.
Voyons 🙂

OriginalL'auteur Berryl | 2010-12-08