Представление WPF устанавливает свойства ViewModel в NULL на закрытии

Вот мои наблюдения: -----> 1. После событий завершения: во время создания событие завершения не может быть передано в CountDownLatch, но оно может быть задано в CyclicBarrier.

  1. Количество: При создании CyclicBarrier число рабочих потоков не включает основной поток, если он также ожидает завершения других потоков. При создании CountDownLatch просто необходимо указать, сколько рабочих потоков будет ждать основной поток, чтобы завершить. В CountDownLatch существует концепция основного и рабочего потоков, и основной ожидающий поток не учитывается при создании защелки.

  2. Намерение await (): В CyclicBarrier :: await () все потоки, включая основной, равны и ждут друг друга. Следовательно, await () следует указывать во всех потоках (как рабочих, так и основных). CountDownLatch :: await () дается только в основном потоке и заставляет основной поток ждать, пока другие рабочие потоки не подсчитают до 0. Таким образом, внутренняя реализация обоих await () отличается.

  3. Стороны и ожидающие потоки: CountDownLatch не может дать число ожидающих потоков, но может дать стороны (cl.getCount ()), CyclicBarrier может не дать ожидающих потоков cb.getNumberWaiting () и стороны (cb.getParties (cb.getParties ( ))

  4. Рабочие обязанности: рабочий поток в обратном отсчете должен выполнять обратный отсчет (), а ожидание () выполняется одним основным потоком. В cyclicBarrier рабочий и основной потоки все делают только await () друг на друга.

  5. Повторное использование: CyclicBarrier можно использовать повторно. cb.await () работает для новых потоков, скажем, t1, t2 и main. И второй вызов cb.await () для новых потоков t3, t4 и main также работает. Main будет ожидать обоих вызовов, то есть система автоматически сбрасывает счет (или сбрасывает ()) после выхода из барьера. CountDownLatch не может быть повторно использован. - cl.await () работает для новых потоков, скажем, t1, t2 и main. Основной поток ожидает завершения t1, t2. Но для второго вызова cl.await () новые потоки t3, t4 и main не будут ждать.

Вот код для его поддержки ....

static class MyThread implements Runnable
{
    long waitTime;
    CyclicBarrier cyclicBarrier;
    CountDownLatch countdownlatch;
    MyThread(  long waitTime, CyclicBarrier cyclicBarrier, CountDownLatch countdownlatch){
        this.waitTime = waitTime;
        this.cyclicBarrier = cyclicBarrier;
        this.countdownlatch = countdownlatch;
    }
    @Override
    public void run() {

            try {

                Thread.sleep(waitTime);

                // Diff 4 -----> countdownlatch worker threads need to do countdown and await is done by one single main thread
                //, cyclicBarrier worker threads await on each other
                countdownlatch.countDown(); 
                cyclicBarrier.await();

                System.out.println("cyclicBarrier :: " + 
                        ", name :: " + Thread.currentThread().getName() 
                        + ", parties :: " + cyclicBarrier.getParties() 
                        + ", waiting :: "+ cyclicBarrier.getNumberWaiting()); 

                System.out.println("countdownlatch :: " + 
                            "name :: " + Thread.currentThread().getName()  +
                         ", parties :: "+countdownlatch.getCount() +
                         ", waiting :: " + "No method!!" ); 
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

    }

}

public static class MyCBFinishEvent implements Runnable{

    public void run() {

           System.out.println("All threads have reached common barrier point "
                        + ", CyclicBarrrierFinishEvent has been triggered");
           System.out.println("You can update shared variables if any");
    }

}

public static void main(String [] args) throws InterruptedException, BrokenBarrierException{
    //Diff 1 ----- > No finish event can be given in CountDownLatch
    //Diff 5 ------> CyclicBarrier no of worker threads includes main thread, 
    //CountDownLatch is just how many threads, the main waiting thread is not included in count.
    CyclicBarrier cb = new CyclicBarrier(3, new MyCBFinishEvent());
    CountDownLatch cl = new CountDownLatch(2);

    //Diff 2 ----> CountDownLatch cant give num of waiting threads, CyclicBarrier can getNumberWaiting threads
     System.out.println("Start CyclicBarrier - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("Start CountDownLatch - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

    Runnable t1 = new Thread(new MyThread( 10000, cb, cl));
    Runnable t2 = new Thread(new MyThread( 5000, cb, cl));
     Thread tt1 = new Thread(t1, "t1");
     Thread tt2 = new Thread(t2, "t2");
     tt1.start();
     tt2.start();

     //Diff 6 ---- > await meaning Main waits for t1 and t2 to complete, 
     //CyclicBarrier all are equal. each thread including main thread, if it wants to wait has to do await. 
     //CountDownLatch concept of waiting and workers. main thread await waits till other worker threads make count to 0.
     cb.await();
     cl.await();

     System.out.println("End CyclicBarrier call 1 - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("End CountDownLatch call 1 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     System.out.println("main start created t3, t4 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     Runnable t3 = new Thread(new MyThread( 6000, cb, cl));
        Runnable t4 = new Thread(new MyThread( 100, cb, cl));
         Thread tt3 = new Thread(t3, "t3");

         Thread tt4 = new Thread(t4, "t4");

         tt3.start();
         tt4.start();

        //Diff -3 -----> 
         //CyclicBarrier - can be reused, main thread waited for t3, t4 to complete.
         //CountDownLatch - for first cl.await(), main waited... second cl.await() call main did not wait!!! 
         cb.await();
         cl.await();


         System.out.println("End main - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
         System.out.println("end main parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

}
7
задан Dan Fuller 16 June 2009 в 15:12
поделиться

2 ответа

Я нашел одно возможное решение, но оно мне действительно не нравится.

Оказывается, DataContext уже имеет значение null, но это не помогает. Это происходит до того, как для свойства будет установлено значение null. Кажется, что происходит то, что привязки данных не удаляются до того, как UserControl / View избавляется от себя, и поэтому нулевое значение распространяется вниз, когда элемент управления удаляется.

Итак, когда DataContext изменяется, если новый контекст имеет значение null, то я удаляю соответствующие привязки в ComboBox следующим образом:

private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (e.NewValue == null)
    {
        SupervisorDropDown.ClearValue(ComboBox.SelectedValueProperty);
    }
}

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

0
ответ дан 8 December 2019 в 01:47
поделиться

When I display a different UserControl, I keep the ViewModel of the previous control active, but the Views are discarded automatically by WPF.

The problem that I'm having is that when the view shuts down, any two way bindings to the properties in the ViewModel are immediately set to null, and so when I display the ViewModel again all of the values are just set обнулить в пользовательском интерфейсе.

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

0
ответ дан 8 December 2019 в 01:47
поделиться
Другие вопросы по тегам:

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