非常奇怪的错误与C#中的属性

时间:2008-10-28 07:59:01

标签: c# .net properties

我有一个应用程序,在将新信息与旧信息进行比较后,将信息提供给对象。 它类似于

set
{
    oldval=_value;
    _value=value;
    if (some comparison logic)
        raiseEvent();
}

这一切都发生在后台线程中,在无限循环中,间歇性地休眠100ms。 真正奇怪的部分是它第一次工作,比较逻辑变为真,事件被提升。 在那之后,信息不断流动,它继续进入对象,我知道这是因为我设置MessageBoxes一直显示旧值和新值,但它好像它以某种方式绕过了set子句! 我在子句的开头设置了一个消息框,它只是没有弹出! 这真的很奇怪,因为我确信该值不断更新。

有什么想法吗?


是的,我知道,但不幸的是,我能表现得更多...... 让我试着再次解释整体结构: 我有一个单独的后台线程运行无限循环。 此循环不断从Data对象中提取数据,该对象由另一组线程更新。 所有这些当然与Monitor.Enter和Exit同步。 然后,从Data对象中提取的数据将输入到Comparer对象中。

while(true)
{
    Thread.Sleep(100);
    Monitor.Enter(Data);
    Comparer.Value = Data.Value;
    Monitor.Exit(Data);
}

Comparer.Value是我在第一篇文章中提到的属性。 因为我在循环结束时设置了一个MessageBox,所以非常奇怪:

MessageBox.Show(Comparer.Value + " - " + Data.Value);

并且值DO实际更新,它只是以某种方式似乎绕过了set子句,这是不可能的...... 这真的很奇怪。

而Rob,循环不进行任何检查,它只是模拟Comparer.Value中的信息流;它的set子句包含比较逻辑。

bh213,我很漂亮,但是我无法分辨,因为比较在任何有意义的检查完成之前就停止了。


好吧,我已经解决了这个问题,显然我的问题是错的,问题出在其他地方。 感谢所有帮助,问题可能会被关闭。

6 个答案:

答案 0 :(得分:5)

如果没有一些有意义的代码,我们只能猜测。特别是,如果没有出现将MessageBox添加到Set的开头,那么很可能问题出在调用代码上(而不是这个)。

但有些想法 - 特别是因为你有多个主题:

  • 某处有线程竞赛吗?是否应该同步某些代码?
  • 工人得到了非易失性价值的陈旧副本吗?
  • 线程相关性:是涉及工作者和UI的事情吗?
  • 您确定您拥有正确的实例(即,触发事件的对象可能与您正在侦听的对象不同)吗?

可能不是这些;没有一些示例代码,我们无法提供帮助。

我用粗体标记了线程亲和力,因为如果您的工作人员正在进行UI正在侦听的(通过事件)进行更改,这是一个非常可能的问题; UI事件处理程序必须切换到UI线程以更新UI:

void SomeHandler(object sender, EventArgs args)
{
    this.Invoke((MethodInvoker)delegate {
       this.Text = "Something happened";
    });
}

答案 1 :(得分:2)

以前的答案完全正确,因为您需要提供更多信息。

但我可以问为什么你这样做吗?当设置值时,您的业务模型肯定会引发事件,为什么后台线程会间歇性地检查?

也许我只是错过了一些东西,但似乎这里可能存在导致真正的问题的设计缺陷。

答案 2 :(得分:2)

Spam System.Diagnostic.Debug.WriteLine而不是messageboxes。 这些(或者至少它们只做到最小)改变了指令流并且没有线程问题(除了可能的坏输出)。

此外,根据描述,似乎一个简单的调试会话与一些精心设置的断点可能会有所帮助。

第三,什么是“(某种比较逻辑)”?

如果是简单的(oldval!= _value)将其重写为

set
{
 if (_value != value)
 {
  _value=value;
  RaiseSomeEvent();
 }
}

它更干净,你没有机会在没有引发事件的情况下改变_value(除了没有订阅的处理程序..)。

否则“(某些比较逻辑)”表达式可能是错误的位置。

答案 3 :(得分:1)

你真的需要提供更多信息。我们在这里得到的只是一些伪代码。尝试提出一个可以证明问题的short but complete program

答案 4 :(得分:0)

由于在后台线程上引发了事件,因此所有事件处理程序都在该(后台)线程上运行。你的代码是否正确处理了这个问题?

答案 5 :(得分:0)

正如其他人所说,你真的需要创建一个小例子来展示问题。

您可能会在创建此示例应用时自己注意到问题的根源。