WPF: how to invoke a method in a separate thread with a delay time

谁说胖子不能爱 提交于 2019-12-22 08:45:00

问题


I have a TextBox that user can enter search-term in it. Its bind to string Term property in my view-model. And I want to do a search query when its content changed. But I want to do the query in a separate thread with a delay.

e.g. when user type a letter, I want to wait for 0.3 second, and if user change the input within this time (0.3 second), the timer resets and starts again. Otherwise, I start a new thread and do the search query. While query is executing, if user change the term again, abort prev query and start again.

I know how to do this in windows-forms with threading and Timer class. But I'm new to WPF and I'm searching if there is a way specified for WPF threading functionality (or may be a way with a better performance).

Have you any idea? Can you help me?


回答1:


You could use DispatcherTimer. On each keypress, stop the timer if it's already running, then start it. I believe (and you should check this!) that that will reset it.

If it fires, you then take the current value in the textbox and start performing the operation in a separate thread (e.g. using Task.Factory.StartNew, if you're using .NET 4, or BackgroundWorker, or just creating a new thread).

Basically that separates the "new thread" part from the "do I really want to do something" part, keeping everything on the UI thread until the point where you've decided you really do want to do something (and you know the value you want to use).




回答2:


You might want to look into the Reactive Extensions from Microsoft. Rx provides a way to aggregate these types of events into a single event, once a certain delay has passed.

Phil Haack (formerly of Microsoft) had a good article on his blog where he talks about the throttling capability.




回答3:


This just builds on what Jon Skeets said. Give the check mark to him. The .stop() appears to reset the timer.

public MainWindow()
{
    InitializeComponent();

    backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.WorkerSupportsCancellation = true;
    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
    backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);

    dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
    dispatcherTimer.Interval = new TimeSpan(0, 0, 4);
}

public string Input
{
    get { return input; }
    set
    {
        if (value == input) return;
        value = value.Trim();
        input = value;
        NotifyPropertyChanged("Input");

        if (backgroundWorker1.IsBusy) backgroundWorker1.CancelAsync();
        dispatcherTimer.Stop();                
        dispatcherTimer.Start();
    }
 }

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    dispatcherTimer.Stop();
    if (!backgroundWorker1.IsBusy)
    {
        backgroundWorker1.RunWorkerAsync(Input);
    }
}


来源:https://stackoverflow.com/questions/10523677/wpf-how-to-invoke-a-method-in-a-separate-thread-with-a-delay-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!