Простая асинхронная операция со сценарием продолжения не работает в приложении WPF - PullRequest
0 голосов
/ 08 декабря 2011

У меня действительно простая операция в приложении WPF, чтобы попробовать асинхронные операции.Вот мой полный код:

static int GetPrimes() {

    var query =
        from n in Enumerable.Range(3, 5000000).AsParallel()
        where Enumerable.Range(2, (int)Math.Sqrt(n)).All(i => n % i > 0)
        select n;

    return query.Count();
}

private void button1_Click(object sender, RoutedEventArgs e) {

    Task<int> task = Task.Factory.StartNew(
        () => GetPrimes(),
        TaskCreationOptions.LongRunning
    );

    task.ContinueWith(x => {
        label1.Content = task.Result; 
    });
}

Как вы видите, когда я нажимаю кнопку, она делает что-то, а когда она заканчивается, ей нужно перенести результат на метку, но это не так.

Я проверил это синхронно, и это сработало.

Что мне здесь не хватает?

Ответы [ 2 ]

3 голосов
/ 08 декабря 2011

Вы не объясняете, что означает "он этого не делает".Я предполагаю, что вы получаете исключение, потому что вы пытаетесь манипулировать элементом пользовательского интерфейса из неправильного потока?

Проблема в следующем коде:

task.ContinueWith(x => {
    label1.Content = task.Result; 
});

Вы не указываете, какойвы хотите, чтобы ваше продолжение продолжалось, чтобы оно могло работать в любом потоке.Вероятно, он будет выполняться в том же потоке, что и ваша первая задача, т. Е. В потоке пула потоков.Поскольку вам не разрешен доступ к пользовательскому интерфейсу из потока, отличного от потока, в котором он был создан, это означает, что ваше назначение label1.Content завершится неудачей с исключением.

Исправление простое: запустите продолжение наПользовательский интерфейсИзмените приведенный выше код на это:

task.ContinueWith(x => {
    label1.Content = task.Result; 
}, TaskScheduler.FromCurrentSynchronizationContext());
0 голосов
/ 08 декабря 2011

Поскольку вы работаете с фоновыми потоками, вам нужно будет маршалировать любой код, который воспроизводится с пользовательским интерфейсом, в поток пользовательского интерфейса.

task.ContinueWith(x => {
    Dispatcher.Invoke(() =>
        {
        label1.Content = task.Result; 
        },
        null);
});
...