在C#wpf应用程序中处理线程

时间:2014-07-25 00:23:59

标签: c# wpf multithreading delegates thread-safety

我正在使用Visual Studio 2012创建一个C#wpf应用程序。有两个名为textboxInput和textboxOutput的文本框。我的任务是当我输入textboxInput时,它应该通过搜索数据库将实时细节带入textboxOutput。由于这需要一些时间,因此会降低用户不想要的打字速度。

当用户输入“foo”时,它会搜索“f”,然后搜索“fo”然后搜索“foo”。有所有这些的数据库条目。用户只想查看“foo”的详细信息而不是其他人。但我无法预测他会在哪里停止打字。我想给他一个平稳的打字而不会滞后。所以我的想法是使用线程。在testChanged事件中,我使用Thread搜索它,如果它再次进入textChange事件(键入另一个字母),它将杀死前一个线程并运行一个新线程。

我目前的做法。

private void textBoxInput_TextChanged(object sender, TextChangedEventArgs e){
    //textBoxOutput.Text=search(textBoxInput.Text);  //previos approach

    //Current approach
    new Thread(delegate() {search(textBoxInput.Text); }).Start();
}

你可以帮我解决一下

中的代码吗?
  1. 我当前的代码给了我异常“调用线程无法访问此对象,因为另一个线程拥有它”。如何处理?
  2. 如何实现以前的线程查杀机制? (我是初学者:))
  3. 还有其他好方法可以完成我的任务吗?

2 个答案:

答案 0 :(得分:3)

你可以这样做:

   Thread thread;
            bool flag = false;
            public MainWindow()
            {
                InitializeComponent();
                thread = new Thread(new ThreadStart(search));
                thread.Start();
            }

            private void textBoxInput_TextChanged(object sender, TextChangedEventArgs e)
            {
                if(flag)
                   return;
                flag = true;
            }

            private void search()
            {
                while(true)
                {
                    if(flag)
                    {
                        string result = search(textBoxInput.Text);
                        this.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            textBoxOutput.Text = result;
                        }));
                        flag = false;
                    }
                    Thread.Sleep(200);
                }
            }

永远不要这样做: it kills the previous thread and runs a new Thread

答案 1 :(得分:1)

关键是你无法从后台线程访问UI元素 - 例如textBoxInput。因此,您必须首先创建Text属性的本地副本:

string text = textBoxInput.Text;
new Thread(delegate() { search(text); }).Start();

此外,如果“搜索”功能执行某种UI操作(我认为它会这样做),那么您需要使用Dispatcher.BeginInvoke()将该操作发送回UI线程:

Dispatcher.BeginInvoke(new Action(() => {
    // UI operation here
}));