Pokazywanie postów oznaczonych etykietą foreach. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą foreach. Pokaż wszystkie posty

poniedziałek, 18 lutego 2013

[C#|Visual Studio] Threading: klasa Parallel

Kolejną ciekawą funkcjonalnością wprowadzoną w .NET 4.0 jest klasa Parallel. Udostępnia ona trzy metody umożliwiające zrównoleglenie wykonywania kodu.
  • Invoke - wykonuje równolegle tablicę delegatów
  • For - pętla for wykonywana równolegle
  • Foreach - pętla foreach wykonywana równolegle
Metody te zapewniają wysoką wydajność przy zrównoleglaniu obliczeń, ponieważ wykorzystują mechanizm Tasków, zatem np. gdy podamy sto delegatów, to zostaną one rozpartycjonowane na taką ilość tasków, by zapewnić maksymalną efektywność.Wykonywania każdej z tej funkcji zakończy się, gdy skończą działanie wszystkie taski.

static void InvokeTest()
{
    Parallel.Invoke(() => new WebClient().DownloadString("http://www.agh.edu.pl/"),
        () => new WebClient().DownloadString("http://www.eaiib.agh.edu.pl/"));
}

static void ForTest()
{
    var keyPairs = new string[6];
    Parallel.For(0, keyPairs.Length,
                  i => keyPairs[i] = RSA.Create().ToXmlString(true));
    foreach (var keyPair in keyPairs)
        Console.Write(keyPair);
}

static void ForeachTest()
{
    var arr = new int[]
                  {
                      166, 147, 159, 156
                  };
    Parallel.ForEach(arr, 
        s => Console.WriteLine("Alfa Romeo {0}", s));
}

Metoda For jest przeładowana na wiele sposobów. Jeżeli potrzebujemy, by wykonywać skomplikowane operacje matematyczne, możemy skorzystać z wersji metody, w której możemy wykorzystać lokalną zmienną, inicjalizowaną przez jednego z delegatów.

static void ForLockerTest()
{
    object locker = new object();
    double grandTotal = 0;

    Parallel.For(1, 10000000,
      () => 0.0,
      (i, state, localTotal) =>
         localTotal + Math.Sqrt(i),
      localTotal =>
      { lock (locker) grandTotal += localTotal; }
    );

    Console.WriteLine(grandTotal);
}

sobota, 22 września 2012

[HTML|JS|CSS] KnockoutJS : Kolekcje

Data binding do kolekcji elementów jest czymś powszechnie stosowanym. Potrzeba wyświetlania zestawów danych na własne potrzeba pojawia się przy każdym większym projekcie. KnockoutJS daje możliwość prostego bindingu przy użyciu atrybutów oraz odpowiednich typów w ViewModelu.

Wyświetlanie kolekcji

Binding do kolekcji tworzy się w widoku za pomocą dyrektywy foreach, a po dwukropku podajemy nazwę kolekcji z ViewModelu. Jeżeli w przykładzie poniżej people jest kolekcją obiektów, to name, surname oraz added są kolejnymi properties takich obiektów.

<div data-bind="foreach: people">
 <div>
      <strong data-bind="text: name"></strong>
      <strong data-bind="text : surname"></strong>
      <strong data-bind="text : added"></strong> 
 </div>
</div>

W ViewModelu kolekcja musi być typu ko.observableArray, co zapewni śledzenie zmian. Warto przygotować sobie również funkcję - konstruktor do szybkiego tworzenia obiektów.

//funkcja konstruktora dla osoby

function Person(name, surname){
 var self = this;
 self.name = name; 
 self.surname = surname;
 self.added = new Date();
}

function AppViewModel() {

    // pozostala czesc inicjalizacji
    
    this.people = ko.observableArray([
     new Person("John","Doe"),
     new Person("Jack","The Ripper")
     ]);   
}

ko.applyBindings(new AppViewModel());

Powyższy kod wyświetli dane sformatowane do naszych potrzeb.

Dodawanie elementów

Jeżeli zajdzie potrzeba dynamicznego dodawania do kolekcji elementów, można stworzyć odpowiednią funkcję wewnątrz ViewModelu.
Od strony widoku można dodać przycisk z bindingiem do zdarzenia click.

<button data-bind="click: addPerson">Add</button>

W ViewModelu należy z kolei dodać funkcję, w której zwiększamy kolekcję używając funkcji push. Wszystkie zmiany w kolekcji spowodują automatyczne zmiany w widoku.

function AppViewModel() {
    //pozostala czesc inicjalizacji
    var that = this;
    this.addPerson = function(){
     that.people.push(new Person(that.firstName, that.lastName));      
    };
}

Edytowanie elementów

Dzięki śledzeniu zależności, każda zmiana wartości automatycznie odświeży kolekcję. Aby edytować elementy za pomocą elementu select, należy nieco zmodyfikować widok:

<div data-bind="foreach: people">
   <div>
 <!--pozostale elementy-->
 <select data-bind="options: $root.jobs, value: job, optionsText: 'name'"></select>
 <strong data-bind="text : job().salary"></strong>
   </div>
</div>

Obiekt select dostaje informacje o tym, z której kolekcji ma pobierać listę wartości (tablica jobs z ViewModelu), do którego property elementu z kolekcji people przypisać wartość (obserwowalny element job) oraz które property z elementów jobs wyświetlać jako opcję do wyboru.

Tymczasem po stronie ViewModelu:

function Person(name, surname,job){
 var self = this;
 //pozostale properties
 self.job = ko.observable(job);
}

function AppViewModel() {    

    this.jobs = [
    {name: "manger", salary : 6000},
    {name: "tester", salary : 2000},
    {name: "developer", salary : 4000}
    ];

    var that = this;
}

Jak widzimy jobs to kolekcja obiektów. Wyświetlamy tylko property name, ale po wybraniu obiektu mamy też dostęp do property salary. Możemy je wyświetlać w widoku za pomocą instrukcji data-bind="text : job().salary", jako odwołanie do property salary z obiektu job, który jest property elementu kolekcji people.

Usuwanie elementów

Po stronie widoku należy dodać element powodujący usunięcie elementu np. poprzez click.

<div data-bind="foreach: people">
 <div>
 <!--pozostale elementy -->
 <a data-bind="click: $root.removePerson">Remove item</a>
 </div>
</div>

Jako lokalizację funkcji podaje się $root, czyli najbardziej zewnętrzny ViewModel.


function AppViewModel() {
    var that = this;

    this.removePerson = function(person){
     that.people.remove(person);
    }
}


Agregacja wartości:

Pisanie swoich funkcji wyliczających pewne wartości na całej kolekcji staje się proste dzięki mechanizmowi śledzenie zależności. Gdy chcemy posumować wszystkie wartości i zbindować tę sumę do osobnego elementu, wartość zostanie odświeżona automatycznie przy każdej zmianie na kolekcji. Możemy także zbindować się do właściwości visible i wyświetlać dany element w zależności od spełnienia pewnego warunku logicznego. Na przykład:

<div data-bind="visible: totalSalary()>0">
 <p>Total salary:</p>
 <strong data-bind="text: totalSalary"></strong>
</div>

gdzie total salary jest typem ko.computed w ViewModelu.


that.totalSalary = ko.computed(function() {
   var total = 0;
   for (var i = 0; i < that.people().length; i++)
       total += that.people()[i].job().salary;
   return total;
});