【问题标题】:How to detect a control being invalidated?如何检测无效的控件?
【发布时间】:2011-05-14 10:06:59
【问题描述】:

我正在实施生产者/消费者问题。代码如下所示:

void producer()
{
  // produce item
  // update some control in form
}

void consumer()
{
  // consume item
  // update some control in form
}

生产者和消费者方法在与创建表单的线程不同的线程中执行,因此我无法更新表单中的控件。我尝试了以下代码:

void producer()
{
  // produce item
  // put the work to be done in a queue
  this.Invalidate();
}

void consumer()
{
  // consume item
  // put the work to be done in a queue
  this.Invalidate();
}

所以现在我必须检测表单是否已失效。我查看了 Form 的事件列表,我能找到的最好的东西是绘画事件。我输入了完成工作的代码,它工作正常。问题是我以某种方式怀疑我是否以正确的方式做到了这一点,尽管它有效。我认为绘画不是做这项工作的正确地方,因为我正在做的不仅仅是绘画。我想知道是否有更好的方法来做到这一点。

编辑 -- 无效事件处理程序的片段不起作用

public Form1()
{
  InitializeComponent();
  this.Invalidated += InvalidateEventHandler;
}
void producer(object o)
{
  // produce
  // put work in queue
  this.Invalidate();
}
public void InvalidateEventHandler(object sender, InvalidateEventArgs e)
{
  // Do Stuff to form -- Where exception raises
}

【问题讨论】:

    标签: c# winforms invalidation


    【解决方案1】:

    Invalidate 旨在触发 Paint。

    您需要在表单上Control.Invoke() 您自己的刷新方法。

    编辑:

    您的非 GUI 线程甚至不应该调用 Invalidate(),它们不能接触 GUI。

    您可以编写自己的 ProcessData() 表单方法并通过 Prod/Cons 调用 mainForm.Invoke(ProcessData)

    然后ProcessData() 负责线程安全地访问数据和使 GUI 无效

    【讨论】:

    • 也许我不明白,但这如何解决我的执行线程不是创建者的问题?你能解释一下吗?
    【解决方案2】:

    你可以尝试使用new关键字来实现你自己的Invalidate

        public new void Invalidate()
        {
            // place your logic here
            base.Invalidate();
        }
    

    Aslo Form 有 Invalidated 事件,在 Ivalidate 结束后触发

    编辑:

    public void InvalidateEventHandler(object sender, InvalidateEventArgs e)
    {
        anotherForm.Invoke(new Action(() =>
        {
            // Do Stuff to form -- Where exception raises
        }));
    }
    

    【讨论】:

    • @Stecya ARGH!是的,它确实有 Invalidated 事件,但它没有显示在属性窗口中,为什么,我在代码中尝试过它并显示了它。但是关于使用我自己的 Invalidate() 实现,不,它不会起作用,因为我使用创建表单的线程以外的线程调用 Invalidate,所以它将是执行 Invalidate 的线程,我将拥有同样的问题。
    • 那么使用事件就是你的解决方案
    • 不幸的是,它不起作用,我不知道为什么。我向 Invalidated 事件添加了一个新的事件处理程序,当它被执行时,我得到了同样的错误,即它是从创建表单的线程之外的另一个线程更新的。 :(
    • 您应该使用 Invoke 与来自不同线程的其他表单进行交互。查看我的编辑
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 2011-10-05
    • 2011-09-24
    相关资源
    最近更新 更多