Используя Диспетчера WPF в модульных тестах

Паркет не предоставляет встроенную поддержку векторов Spark ML / MLlib и не является первоклассными гражданами в Spark SQL.

Вместо этого Spark представляет Vectors, используя поля struct с тремя полями:

  • type - ByteType
  • size - IntegerType (необязательно) только для SparseVectors)
  • indices - ArrayType(IntegerType) (необязательно, только для SparseVectors)
  • values - ArrayType(DoubleType)
[1119 ] и использует метаданные, чтобы отличать их от простых structs и оболочек UDT для отображения на внешние типы. Преобразование между разреженным и плотным представлением не требуется. Тем не менее, в зависимости от данных, для такого представления может потребоваться сопоставимая память с полным плотным массивом.

Обратите внимание, что OOM при записи не обязательно относится к самому процессу записи. Поскольку Spark, как правило, ленив, исключение может быть вызвано любой из вышестоящих стадий.

47
задан abatishchev 2 March 2012 в 08:24
поделиться

7 ответов

By using the Visual Studio Unit Test Framework you don’t need to initialize the Dispatcher yourself. You are absolutely right, that the Dispatcher doesn’t automatically process its queue.

You can write a simple helper method “DispatcherUtil.DoEvents()” which tells the Dispatcher to process its queue.

C# Code:

public static class DispatcherUtil
{
    [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
    public static void DoEvents()
    {
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
            new DispatcherOperationCallback(ExitFrame), frame);
        Dispatcher.PushFrame(frame);
    }

    private static object ExitFrame(object frame)
    {
        ((DispatcherFrame)frame).Continue = false;
        return null;
    }
}

You find this class too in the WPF Application Framework (WAF).

86
ответ дан 7 November 2019 в 12:59
поделиться

Winforms имеет очень легкое и совместимое решение WPF.

Из Вашего проекта модульного теста, ссылочной Системы. Windows. Формы.

От Вашего модульного теста, когда Вы хотите ожидать событий диспетчера, чтобы закончить обрабатывать, звоните

        System.Windows.Forms.Application.DoEvents();

, Если у Вас есть фоновый поток, который продолжает добавлять, Вызывает очереди диспетчера, тогда Вы должны будете иметь своего рода тест и продолжать называть DoEvents до фона, некоторое другое тестируемое условие соблюдают

        while (vm.IsBusy)
        {
            System.Windows.Forms.Application.DoEvents();
        }
0
ответ дан 7 November 2019 в 12:59
поделиться

Когда вы вызываете Dispatcher.BeginInvoke, вы инструктируете диспетчер запускать делегаты в своем потоке , когда поток простаивает .

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

Чтобы сделать этот аспект модульным тестируемым, вам придется изменить базовый дизайн, чтобы он не использовал диспетчер основного потока. Другой альтернативой является использование системы . ComponentModel.BackgroundWorker для изменения пользователей в другом потоке. (Это всего лишь пример, в зависимости от контекста он может быть неприемлемым).


Редактировать (5 месяцев спустя) Я написал этот ответ, не зная о DispatcherFrame. Я очень рад, что ошибся в этом - DispatcherFrame оказался чрезвычайно полезным.

2
ответ дан 7 November 2019 в 12:59
поделиться

Я понял, что GDI + использует WIC для выполнения определенных задач. По крайней мере, в Windows 7 это так.

Обратите внимание на следующий код:

image.Write(target, ImageFormat.Gif);

Когда я запускаю этот код в Windows XP, он будет использовать кодировщик GDI + Gif для записи изображения в формате Gif. Когда я запускаю тот же код под Windows 7, он будет использовать WIC Gif Encoder.

Все методы автоматической регистрации зависят от кода времени загрузки и его способов избежать статического фиаско, как функция, которая создает объект и возвращает его по запросу.

Но если вам не удастся загрузить то, что никогда не будет работать, объединение объектных файлов вместе сработает и также загрузит динамические библиотеки, но статические библиотеки никогда не будут компоноваться без явных зависимостей.

по крайней мере, для меня этого всегда было достаточно для тестирования чего-либо, связанного с DependencyObject / WPF.

Если вы хотите попробовать это, я могу указать вам несколько способов сделать это:

  • Если вы используете NUnit> = 2.5. 0 есть атрибут [RequiresSTA] , который может нацеливаться на методы или классы тестирования. Однако будьте осторожны, если вы используете интегрированное средство выполнения тестов, поскольку, например, средство выполнения R # 4.5 NUnit, похоже, основано на более старой версии NUnit и не может использовать этот атрибут.
  • В более старых версиях NUnit вы можете настроить NUnit для использования [STAThread] поток с файлом конфигурации, см., Например, это сообщение в блоге Криса Хедгейта.
  • Наконец, в том же сообщении в блоге есть резервный метод (который я успешно использовал в прошлом) для создания собственного потока [STAThread] для запуска вашего теста.
1
ответ дан 7 November 2019 в 12:59
поделиться

Вы можете выполнить модульное тестирование с помощью диспетчера, вам просто нужно использовать DispatcherFrame. Вот пример одного из моих модульных тестов, который использует DispatcherFrame для принудительного выполнения очереди диспетчера.

[TestMethod]
public void DomainCollection_AddDomainObjectFromWorkerThread()
{
 Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
 DispatcherFrame frame = new DispatcherFrame();
 IDomainCollectionMetaData domainCollectionMetaData = this.GenerateIDomainCollectionMetaData();
 IDomainObject parentDomainObject = MockRepository.GenerateMock<IDomainObject>();
 DomainCollection sut = new DomainCollection(dispatcher, domainCollectionMetaData, parentDomainObject);

 IDomainObject domainObject = MockRepository.GenerateMock<IDomainObject>();

 sut.SetAsLoaded();
 bool raisedCollectionChanged = false;
 sut.ObservableCollection.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
 {
  raisedCollectionChanged = true;
  Assert.IsTrue(e.Action == NotifyCollectionChangedAction.Add, "The action was not add.");
  Assert.IsTrue(e.NewStartingIndex == 0, "NewStartingIndex was not 0.");
  Assert.IsTrue(e.NewItems[0] == domainObject, "NewItems not include added domain object.");
  Assert.IsTrue(e.OldItems == null, "OldItems was not null.");
  Assert.IsTrue(e.OldStartingIndex == -1, "OldStartingIndex was not -1.");
  frame.Continue = false;
 };

 WorkerDelegate worker = new WorkerDelegate(delegate(DomainCollection domainCollection)
  {
   domainCollection.Add(domainObject);
  });
 IAsyncResult ar = worker.BeginInvoke(sut, null, null);
 worker.EndInvoke(ar);
 Dispatcher.PushFrame(frame);
 Assert.IsTrue(raisedCollectionChanged, "CollectionChanged event not raised.");
}

Я узнал об этом здесь .

17
ответ дан 7 November 2019 в 12:59
поделиться

Создание DipatcherFrame отлично поработало для меня:

[TestMethod]
public void Search_for_item_returns_one_result()
{
    var searchService = CreateSearchServiceWithExpectedResults("test", 1);
    var eventAggregator = new SimpleEventAggregator();
    var searchViewModel = new SearchViewModel(searchService, 10, eventAggregator) { SearchText = searchText };

    var signal = new AutoResetEvent(false);
    var frame = new DispatcherFrame();

    // set the event to signal the frame
    eventAggregator.Subscribe(new ProgressCompleteEvent(), () =>
       {
           signal.Set();
           frame.Continue = false;
       });

    searchViewModel.Search(); // dispatcher call happening here

    Dispatcher.PushFrame(frame);
    signal.WaitOne();

    Assert.AreEqual(1, searchViewModel.TotalFound);
}
2
ответ дан 7 November 2019 в 12:59
поделиться

Мы решили эту проблему, просто высмеяв диспетчера за интерфейсом, и извлекаем интерфейс из нашего контейнера IOC. Вот интерфейс:

public interface IDispatcher
{
    void Dispatch( Delegate method, params object[] args );
}

Вот конкретная реализация, зарегистрированная в контейнере IOC для реального приложения

[Export(typeof(IDispatcher))]
public class ApplicationDispatcher : IDispatcher
{
    public void Dispatch( Delegate method, params object[] args )
    { UnderlyingDispatcher.BeginInvoke(method, args); }

    // -----

    Dispatcher UnderlyingDispatcher
    {
        get
        {
            if( App.Current == null )
                throw new InvalidOperationException("You must call this method from within a running WPF application!");

            if( App.Current.Dispatcher == null )
                throw new InvalidOperationException("You must call this method from within a running WPF application with an active dispatcher!");

            return App.Current.Dispatcher;
        }
    }
}

А вот макет, который мы вводим в код во время модульных тестов:

public class MockDispatcher : IDispatcher
{
    public void Dispatch(Delegate method, params object[] args)
    { method.DynamicInvoke(args); }
}

У нас также есть вариант ] MockDispatcher , который выполняет делегатов в фоновом потоке, но в большинстве случаев это не обязательно

21
ответ дан 7 November 2019 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: