Реактивные расширения, блокировки и потоки - PullRequest
4 голосов
/ 08 декабря 2010

Я использую реактивные расширения для работы с пользовательским интерфейсом wpf, в основном у меня есть текстовое поле, которое мне нужно и для сэмплирования, и для дросселирования (некоторые вещи выполняются непрерывно во время набора текста, а некоторые - когда перестают печатать) на небольших промежутках времени (200-300 мс)

Проблема в том, что это несколько непредсказуемо и иногда сразу же запускает газ, это может быть связано с тем, что событие TextUpdated не дошло до наблюдаемого или чего-то другого с самим наблюдаемым. Я также делаю некоторые блокировки, которые могут мешать, но обычно это делается с помощью новых задач, а не в потоке пользовательского интерфейса. У меня также есть подозрение, что отладка может повлиять на поведение, так как она кажется более «некорректной», когда я устанавливаю контрольные точки

Поскольку наблюдаемое создается в потоке пользовательского интерфейса, я полагаю (возможно, по ошибке), что это таймер или все, что используется ниже, также в этом потоке, возможно, было бы неплохо создать новый поток для создания наблюдаемых, чтобы оно не мешало накладными расходами пользовательского интерфейса и потенциальной блокировкой? Как мне создать такой поток наилучшим образом, я думаю, что пустой цикл while в конце может быть не очень хорошей идеей:)

Как работает Throttle, Sample и реактивные расширения в связи с потоками под капотом?

EDIT

Кажется, проблема была в том, как я ее тестировал: P Если вы удерживаете клавишу, кажется, что она задерживается на 500 мс, прежде чем она начинает повторяться, если вы просто нажимаете на клавиши, она работает нормально. Вздох

1 Ответ

1 голос
/ 08 декабря 2010

И Sample, и Throttle используют Scheduler.ThreadPool для своего времени, поэтому я сомневаюсь, что это проблема.

Я рекомендую добавить некоторые записи в код, чтобы выяснить, где находится узкое место:

sourceEvents.LogInterval("Source")
    .Throttle(throttleTimeSpan).LogInterval("Throttled")
    .Sample(sampleTimeSpan).LogInterval("Sample")
    .Subscribe();

Вот определение LogInterval:

public static class ObservableEx
{
    public static IObservable<TSource> LogInterval(
        this IObservable<TSource> source, string message)
    {
        return source
            .TimeInterval()
            .Do(x => Debug.WriteLine("{0} :: {1} ({2})", 
                message, x.Value, x.Interval.TotalMilliseconds);
            .RemoveTimeInteval();
    }
}

Если узким местом является дроссель / образец, это, вероятно, означает, что вы насыщаете ThreadPool в другом месте. Если это так, и производительность этих дросселей важна, вы можете рассмотреть возможность создания выделенного потока + диспетчера и использования пользовательского DistpatcherScheduler для дросселя / образца. В качестве альтернативы, может быть более хороший способ решения этой проблемы.

...