1

注:この質問に依存します

やあ。私はこのようなビューモデルを持っています:

public class ViewModel {
    private readonly IPersonService _personService;
    private readonly ObservableCollection<SearchPersonModel> _foundedList;
    private readonly DispatcherTimer _timer;
    private readonly Dispatcher _dispatcher;
    private CancellationTokenSource _tokenSource;

    public SearchPatientViewModel(IPersonService personService) {
        _personService = personService;
        _foundedList = new ObservableCollection<SearchPersonModel>();
        _dispatcher = (/*CurrentApplication*/).Dispatcher;
        _timer = new DispatcherTimer(
            TimeSpan.FromMilliseconds(1000),
            DispatcherPriority.Normal,
            TimerCallBack,
            _dispatcher);
        _tokenSource = new CancellationTokenSource();
    }

    public string Term {
        get { return _term; }
        set {
            // implementing INotifyPropertyChanged
            if(_term== value)
                return;
            _term= value;
            OnPropertyChanged(() => Term);
            tokenSource.Cancel(); // canceling prev search query
            _timer.Stop(); // stop the timer to reset it
            // start it again to do a search query if user change not the term for 1000ms
            _timer.Start(); 
        }
    }

    private void TimerCallBack(object sender, EventArgs e) {
        _timer.Stop();
        _tokenSource = new CancellationTokenSource();
        var task = Task<IEnumerable<SearchPersonModel>>.Factory
            .StartNew(Search, _tokenSource.Token);
        _dispatcher.BeginInvoke((Action)(() => {
            _foundedList.Clear();
            foreach(var item in task.Result)
                _foundedList.Add(item);
        }), DispatcherPriority.Background);
    }

    private IEnumerable<SearchPersonModel> Search() {
        return _personService.DoSearch(this.Term);
    }

}

そして、IPersonService実装ではこれを行います:

public class PersonService : IPersonService {
    public IEnumerable<SearchPersonModel> DoSearch(string term){
        System.Threading.Thread.Sleep(10000);
        return some-search-result;
    }
}

ただし、検索クエリが実行されている間、GUI は自由であることを期待しています。でも凍った!私の間違いがどこにあるのか分かりますか?私を助けてくれませんか?ありがとうございます!

4

1 に答える 1

4

問題は、クエリが完了するまで評価task.Resultがブロックされることです。

おそらく最も簡単なオプションは、代わりにメソッドが最後に呼び出しをSearch実行するようにすることです。_dispatcher.BeginInvoke

もう 1 つのオプション (C# 5 でより簡単になります) は、タスクに継続を追加して、完了時に UI を更新できるようにすることです。現時点では、Task.ContinueWith;を使用します。C# 5 では、 and を使用asyncawaitます。

于 2012-05-10T12:50:06.647 に答える