2016-04-06 21 views
1

Çapraz iş parçacığı hakkında bilgi edindim ve oluşturduğum bir sınıftan (viewmodel) ana kullanıcı arayüzü iş parçacığını nasıl güncelleyebileceğimle ilgili bir sorum var. Topladığımdan, memur gitmek için yoldur. Ana kullanıcı arayüzü işleyicisi dağıtıcısını bir sınıfta nasıl kullanırım? Ya da bunu yapmanın daha iyi bir yolu var. Bu örnekte Sayı Değerine bir metin bloğu veriyorum. Bunu işe almak için ne yapmam gerekirdi. Teşekkürler!Dispatcher ViewModel?

class customVM : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChange(string PropertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); 
     } 
    } 

    private int _count; 

    public int Count 
    { 
     get { return _count; } 
     set { 
      _count = value; 
      OnPropertyChange(nameof(Count)); 
     } 
    } 

    public async void methodAsync() 
    { 
     await method(); 
    } 

    private Task method() 
    { 

     return Task.Run(() => 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       Task.Delay(1000).Wait(); 
       //************* 
       Count = i; 
       //************* 
      } 
     }); 
    } 
    } 
+0

belirsiz bir soru, gönderilen kodda, normal ciltleme çalışacaktır. başka ne yapmaya çalışıyorsun? – AnjumSKhan

+0

Sayım, metin bloğuna bağlanır. Çapraz iş parçacığı oluşur. – user3363744

+0

Unutmayın, çapraz iş parçacığı, WPF uygulamalarında doğrudan bir dağıtıcı kullanmadan çalışır. Farklı platformlar arasında geçiş yapıyorum. – user3363744

cevap

1

PropertyChanged etkinlik otomatik UI dispeçerine sıralıyor olduğunda, UI iş parçacığı için başka bir iş parçacığı PropertyChanged göndermeye gerek yoktur. Bir olarak

private Task method() 
{ 
    //The following code is okay. There is no need to marshal it explicitly   
    return Task.Run(() => 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      Task.Delay(1000).Wait(); 
      //************* 
      Count = i; 
      //************* 
     } 
    }); 
} 

diyor ki: WPF, işler farklıdır ve Şekil 5'te gösterilen kod Durumu tesiste TextBlock için veriyle bile çalışır

Not söyledi. Bu , WPF, diğer tüm XAML çerçevelerinin aksine, PropertyChanged olayını otomatik olarak ana iş parçacığına gönderir. Diğer tüm çerçevelerinde, bir gönderim çözümü gereklidir.

Bununla birlikte, sayısal özellikleri (yani PropertyChanged etkinlik) ile bildirimleri değiştirmek için doğrudur. Koleksiyon değişikliği bildirimleri (INotifyCollectionChanged.CollectionChanged olayı) bu şekilde çalışmaz, UI iş parçacığı üzerinde el ile kaldırılmalıdır. Yani, INotifyCollectionChanged (ObservableCollection ile olduğu gibi) kullanıldığında, bu değişiklikler UI iş parçacığına göre sıralanır. Başka bir deyişle, kullanıcı arayüzü olmayan bir diziden koleksiyonu değiştirirseniz, bir istisna alırsınız. ViewModel sınıfındayız ve kullanıcı arayüzünü güncellemek için Dispatcher'ı kullanmıyoruz. Sadece WPF (ve muhtemelen de Xamarin) çalışır

DispatchService.Invoke(() => 
{ 
    this.MyCollection.Add("new value"); 
}); 

David Rickard article at msdn blog.

2

Çapraz dişli sayıl özellik bağlama:

public static class DispatchService 
{ 
    public static void Invoke(Action action) 
    { 
     Dispatcher dispatchObject = Application.Current.Dispatcher; 
     if (dispatchObject == null || dispatchObject.CheckAccess()) 
    { 
      action(); 
     } 
     else 
     { 
      dispatchObject.Invoke(action); 
     } 
    } 
} 

ve: Ben David Rickard yaklaşımını kullanmak size öneriyoruz. Diğer MVVM platformlarında çalışmaz.

Kodunuz bir tür ilerleme raporu gibi görünüyor. Uygun çözüm Progress<T> ile IProgress<T> geçerli:

class customVM : INotifyPropertyChanged 
{ 
    private int _count; 

    public int Count 
    { 
    get { return _count; } 
    set { 
     _count = value; 
     OnPropertyChange(nameof(Count)); 
    } 
    } 

    public async void methodAsync() 
    { 
    var progress = new Progress<int>(count => { Count = count; }); 
    await Task.Run(() => method(progress)); 
    } 

    private void method(IProgress<int> progress) 
    { 
    for (int i = 0; i < 10; i++) 
    { 
     Thread.Sleep(1000); 
     progress.Report(i); 
    } 
    } 
} 

Progress<T> memurları farklı türde olanlar ve bu WinForms olarak bile olmayan MVVM olanlar dahil tüm UI platformları, oldukça güzel çalışıyor.