使用定时器和数据进行线程处理时的错误

时间:2015-03-03 13:18:44

标签: c# multithreading

我在用户停止在文本框中输入

后实施了一段延迟
private System.Timers.Timer timer = new System.Timers.Timer(1000);

public SearchItem(){
    timer.AutoReset = false;
    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e){
        bindingSource.DataSource = logic.GetData(StockCodeTextBox.Text);
}

private void StockCodeTextBox_TextChanged(object sender, EventArgs e){
        timer.Stop();
        timer.Start();

        if (StockCodeTextBox.Text.Equals("")){
            AllItemsGridView.ClearSelection();
            return;
        }
}

用户停止输入后,为什么会出现此错误?

  

发生类型'System.InvalidOperationException'的异常   在 System.Windows.Forms.dll 中,但未在用户代码中处理

     

其他信息:跨线程操作无效:控制   'AllItemsGridView'从线程以外的线程访问   创建于。

2 个答案:

答案 0 :(得分:3)

您的UI在WinForms UI Dispatcher线程上更新,而您的Timer在后台线程上执行。因此,您无法从不拥有它的线程更新UI。一种解决方法是使用此扩展来从后台线程更新UI:

public static class ControlExtension
{
    public static void Do<TControl>(this TControl control, Action<TControl> action)
    where TControl : Control
    {
        if (control.InvokeRequired)
            control.Invoke(action, control);
        else
            action(control);
    }
}

样品使用:

this.Do(f=>{f.AllItemsGridView.ClearSelection();})

在您的代码中:

private void StockCodeTextBox_TextChanged(object sender, EventArgs e){
    timer.Stop();
    timer.Start();

    this.Do(f=>{
        if (f.StockCodeTextBox.Text.Equals("")){
            f.AllItemsGridView.ClearSelection();
        }
    }
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e){
    this.Do(f=>{ 
       f.bindingSource.DataSource = logic.GetData(f.StockCodeTextBox.Text);
    }
}

如果您可以自由选择解决方案,请考虑使用ReactiveUI和.Net 4.5.2重写您的应用。 https://github.com/AdaptiveConsulting/ReactiveTrader

答案 1 :(得分:0)

如果您使用System.Windows.Forms,则应使用随附的计时器,以免出现交叉线程问题。

而不是System.Timers.Timer使用System.Windows.Forms.Timer