3

私は数日間これを行う方法を理解しようとしています。

これはかなり一般的な問題なので、状況をできるだけ一般的に説明して、他の人が少しでも活用できるようにします。

WPF(MVVMを使用)ダイアログにリストビューがあります。これは、たとえば、別々の列に表示される5つのプロパティを持つアイテムの監視可能なコレクションにバインドされています。

すべてのアイテムを反復処理し、それらのプロパティの 1 つを変更する関数を呼び出します。この関数は、すべての項目を処理するのに時間がかかるため、各項目を更新するようにしたいと考えています。

UI の応答性を維持するためにこれを行うためのオプションは何ですか?実装が最も簡単なのはどれですか?

4

3 に答える 3

4

を使用している場合はC# 4.0

Task.Factory.StartNew(new Action(() =>
{
    .....
     //CALL YOUR UPDATE METHOD



 })).ContinueWith( { //something to execute after, if need}..)

ModelViewそして、他のスレッドからオブジェクトを設定するときは、使用します

Application.Current.Dispatcher.Invoke(new Action(() =>
{
    //set ModelView object properties here
}));
于 2012-10-08T10:54:11.810 に答える
2

別のスレッドでコレクションを更新できるObservableCollectionExtenderを使用します。これは、コレクションを処理するときにアプリケーションで使用するものです。

public class ObservableCollectionExtender<T> : ObservableCollection<T>
{
    /// <summary>
    /// Source: New Things I Learned
    /// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView
    /// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx
    /// Note: Improved for clarity and the following of proper coding standards.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        // Use BlockReentrancy
        using (BlockReentrancy())
        {
            var eventHandler = CollectionChanged;

            // Only proceed if handler exists.
            if (eventHandler != null)
            {
                Delegate[] delegates = eventHandler.GetInvocationList();

                // Walk thru invocation list
                foreach (NotifyCollectionChangedEventHandler handler in delegates)
                {
                    var currentDispatcher = handler.Target as DispatcherObject;

                    // If the subscriber is a DispatcherObject and different thread
                    if ((currentDispatcher != null) &&
                        (currentDispatcher.CheckAccess() == false))
                    {
                        // Invoke handler in the target dispatcher's thread
                        currentDispatcher.Dispatcher.Invoke(
                            DispatcherPriority.DataBind, handler, this, e);
                    }

                    else
                    {
                        handler(this, e);
                    }
                }
            }
        }
    }

    /// <summary>
    /// Overridden NotifyCollectionChangedEventHandler event.
    /// </summary>
    public override event NotifyCollectionChangedEventHandler CollectionChanged;
}
于 2012-10-08T12:49:48.290 に答える
0

簡単な方法として、また Netframework 3.5 で作業している人にとっては、バックグラウンド スレッドで作業し、同期コンテストを使用して同期することができます。これを試して:

        var sync = SynchronizationContext.Current;
        BackgroundWorker w = new BackgroundWorker();
        w.DoWork+=(_, __)=>
            {                    
                foreach (var item in collection)
                {
                   //calculate other things
                   sync.Post(p => { ...Actualize UI code... }, null);                  
                }
             }, null);
            };
        w.RunWorkerAsync();
于 2012-10-08T15:03:32.803 に答える