【问题标题】:Find as you type error backgroundworker in C# winform在 C# winform 中键入错误 backgroundworker 时查找
【发布时间】:2016-06-27 08:45:18
【问题描述】:

我有以下表单,我尝试使用backgroundworker 实现增量搜索。

所以这个想法是用户在顶部键入textbox,并且对于每个击键,下面的listview 被过滤为仅包含包含用户键入的字符的项目。

我最近了解了backgroundworker 组件,因此尝试使用它来过滤和更新listbox

这是textbox的事件代码:

 private void txtSearch_TextChanged(object sender, EventArgs e)
 {
     if (!backgroundWorker1.IsBusy)
     {
         backgroundWorker1.RunWorkerAsync();
     }
 }

backgroundworker 事件是:

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    if (txtSearch.Text != String.Empty)
    {
        GetTheListOfFiles();
        listView.Items.Clear();  << Exception occurs here !

        ...... //some more code to populate the listview control            
    }
}

问题

当我输入textbox 时,我期待listbox 立即响应我的击键并相应地显示过滤后的数据。相反,有大约 8 秒的暂停,然后我收到此错误:

我认为问题是我强调的一点,但我不知道如何解决它。是 backgroundworker 不能用于此目的还是我在实现中遗漏了什么?

PS:我欢迎任何不同的方式来实现这一点。也许更有经验的程序员有更好的解决方案?

更新

这是我正在使用的progresschanged 事件:

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    toolStripProgressBar1.Value = e.ProgressPercentage;
    tsLabelTwo.Text = e.ProgressPercentage.ToString() + @"%";
}

谢谢

【问题讨论】:

  • BackgroundWorker 的 DoWork 事件与您尝试更新的 UI 控件位于不同的线程中。这是一个众所周知的问题,如果要更新控件,则需要引发在 UI 的同一线程中运行的 ProgressChanged 事件
  • 感谢 Steve,我添加了 progresschanged 事件代码。新手问题:我怎么知道将在哪个线程上运行?欢呼
  • 我不确定你的问题。知道哪个线程会运行什么? backgroundWorker1_DoWork 在与创建列表视图控件的线程不同的线程中运行。因此,如果您尝试访问该参考资料,您将面临问题。 ProgressChanged 应该将上下文切换回 UI 线程并让您进行更新。您甚至可以将参数传递给可以在事件处理程序中使用的 ProgressChanged(例如 GetListOfFiles 的结果)

标签: c# winforms listview backgroundworker


【解决方案1】:

如果您使用 UI 线程创建控件,则无法通过其他线程(例如某个后台线程)访问它

只需调用在主线程上抛出跨线程异常的块:

listView.BeginInvoke(new Action(() => { listView.Items.Clear(); }));

【讨论】:

    【解决方案2】:

    如果要更新UI,需要调用控件:

    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
    
            if (txtSearch.Text != String.Empty)
            {
    
                GetTheListOfFiles();
                listView.Dispatcher.BeginInvoke(new Action(() => listView.Items.Clear()), DispatcherPriority.Background);
            }
        }
    

    【讨论】:

      【解决方案3】:

      这是因为您正在尝试从您创建的另一个线程在 UI 线程上运行的控件,这被认为是非法的。正确的解决方法是调用您的控件,在本例中为您的 ListView。

      listView.BeginInvoke(new Action(() => 
      { 
          listView.Items.Clear(); 
          //or perform your UI update or whatever.
      }));
      

      但是,如果您想成为这样的叛逆者并做非法的事情(讽刺),请在 InitializeComponents(); 之后添加这段代码。表单构造函数中的方法。

      Control.CheckForIllegalCrossThreadCalls = false;
      

      但不要,它被称为“非法线程调用”是有原因的 :)

      欲了解更多信息Control.CheckForIllegalCrossThreadCalls Property

      【讨论】:

        猜你喜欢
        • 2010-12-01
        • 2010-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多