Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 2个相互呼叫的事件_C#_Event Handling - Fatal编程技术网

C# 2个相互呼叫的事件

C# 2个相互呼叫的事件,c#,event-handling,C#,Event Handling,我想知道这个问题有一段时间了,但没有真正想出一个解决办法。我有两个不同的事件处理程序递归地互相调用。一旦触发事件A,它就会触发事件B,而事件B会再次触发事件A,以此类推 基本上,我希望能够在RichTextBox中选择文本,并在组合框中显示相应的字体大小。当我从组合框中选择不同的字体大小时,我希望它的值应用于所选文本 这两项活动是: 1) RichTextBox中文本的选择更改事件: private void MyRTB_SelectionChanged(object sender, Route

我想知道这个问题有一段时间了,但没有真正想出一个解决办法。我有两个不同的事件处理程序递归地互相调用。一旦触发事件A,它就会触发事件B,而事件B会再次触发事件A,以此类推

基本上,我希望能够在RichTextBox中选择文本,并在组合框中显示相应的字体大小。当我从组合框中选择不同的字体大小时,我希望它的值应用于所选文本

这两项活动是:

1) RichTextBox中文本的选择更改事件:

private void MyRTB_SelectionChanged(object sender, RoutedEventArgs e)
{
    //Get the font size of selected text and select the concurrent size from the ComboBox.   
}
2) 组合框的选定索引已更改事件:

private void CmbFont_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    //Apply the chosen font size to the currently selected text of the RichTextBox.
}

最好的解决方案是什么,以确保他们每个人都只“做自己的事”,并且在这样做时不触发其他事件?

重构您的代码,以便A调用
DoSomethingA()
,B调用
DoSomethingB()
。这样,如果你想让A实现B的功能,你可以只调用
DoSomethingB()
,而不进行任何递归调用。

重构你的代码,使A调用
DoSomethingA()
,B调用
DoSomethingB()
。这样,如果您想让A执行B的功能,您可以只调用
DoSomethingB()
,而不进行任何递归调用。

只需在调用B之前使用bool(可能称为dontFireA)并将其设置在A中

只需在调用B之前使用bool(可能称为dontFireA)并将其设置在A中

通知属性(用于启用从WPF到非WPF属性的绑定)使用以下技术:

public object MyProperty
{
    get
    {
        return myField;
    }
    set
    {
        if (value != myField)
        {
            myField = value;
            NotifyProperyChanged("MyProperty"); // raise event
        }
    }
}
if(value!=myField)条件防止无限递归(stackoverflowexception)。 在某些情况下(例如浮点数和不准确的值传输),使用if(Math.Abs(value-myField)>someConstant)来中断递归

你能用类似的方法解决你的问题吗

如果两个事件都在同一个对象上,或者所有者彼此有引用,则还可以在每个事件上存储一个标志,例如

private void OnEvent()
{
    DoSomething();
}

private void DoSomething()
{
    this.IsBusy = true;

    // do work

    // raise event
    if (!other.IsBusy)
        RaiseEvent();
}
通知属性(用于启用从WPF到非WPF属性的绑定)使用以下技术:

public object MyProperty
{
    get
    {
        return myField;
    }
    set
    {
        if (value != myField)
        {
            myField = value;
            NotifyProperyChanged("MyProperty"); // raise event
        }
    }
}
if(value!=myField)条件防止无限递归(stackoverflowexception)。 在某些情况下(例如浮点数和不准确的值传输),使用if(Math.Abs(value-myField)>someConstant)来中断递归

你能用类似的方法解决你的问题吗

如果两个事件都在同一个对象上,或者所有者彼此有引用,则还可以在每个事件上存储一个标志,例如

private void OnEvent()
{
    DoSomething();
}

private void DoSomething()
{
    this.IsBusy = true;

    // do work

    // raise event
    if (!other.IsBusy)
        RaiseEvent();
}

有时,更改代码中控件的属性会无意中触发事件。例如,更改列表框或组合框的数据源将触发
SelectedIndexChanged
事件。使用标志处理此情况

private bool _loading;

...

_loading = true;
// Fill the ComboBox or ListView here
_loading = false;
在事件处理程序中,执行此操作

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (_loading) return;
    ...
}

有时,更改代码中控件的属性会无意中触发事件。例如,更改列表框或组合框的数据源将触发
SelectedIndexChanged
事件。使用标志处理此情况

private bool _loading;

...

_loading = true;
// Fill the ComboBox or ListView here
_loading = false;
在事件处理程序中,执行此操作

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    if (_loading) return;
    ...
}

我将做出有根据的猜测,您自己不会引发事件A或事件B;假设事件A是TextBox1.TextChanged事件,事件B是TextBox2.TextChanged事件,它们具有如下处理程序:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   ...
   TextBox2.Text = someString;
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   ...
   TextBox1.Text = someOtherString;
}
在本例中,每个处理程序都将通过更改文本来引发另一个textbox的TextChanged事件,从而导致无限递归

如果希望两者都运行一次且仅运行一次,则可以做的第一件事是标记它们已在运行(更改另一个textbox的文本会导致该textbox的事件处理程序在同一调用堆栈中运行:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   if(handler1Running) return; //the second time through we exit immediately
   handler1Running = true;
   ...
   TextBox2.Text = "Something"; //the other event handler is invoked immediately

   handler1Running = false;
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   if(handler2Running) return; //the second time through we exit immediately
   handler2Running = true;
   ...
   TextBox1.Text = "Something Else"; //the other event handler is invoked immediately

   handler2Running = false;
}
现在,它将深入到三个级别:1的处理程序调用2的处理程序,2的处理程序再次调用1的处理程序,该处理程序看到1的处理程序已经在运行,并在执行任何深化递归的操作之前退出。如果从更改TextBox2开始,情况也是如此

您可以做的另一件事是确保您没有尝试将textbox设置为已经存在的相同值。从一个字符串引用更改为另一个字符串引用,即使两个引用都是相同的字符串值,也会触发TextChanged事件。如果递归必须自然继续,但将达到稳定状态,这实际上是第一次要尝试的事情:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   StringBuilder builder = new StringBuilder();

   ... //build string

   //now, even though the builder's ToString will produce a different reference,
   //we're making sure we don't unnecessarily change the text.
   if(builder.ToString != TextBox2.Text) 
      TextBox2.Text = builder.ToString();       
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   StringBuilder builder = new StringBuilder();

   ... //build string

   //now, even though the builder's ToString will produce a different reference,
   //we're making sure we don't unnecessarily change the text.
   if(builder.ToString != TextBox1.Text) 
      TextBox1.Text = builder.ToString();       
}

我将做出有根据的猜测,您自己不会引发事件A或事件B;假设事件A是TextBox1.TextChanged事件,事件B是TextBox2.TextChanged事件,它们具有如下处理程序:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   ...
   TextBox2.Text = someString;
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   ...
   TextBox1.Text = someOtherString;
}
在本例中,每个处理程序都将通过更改文本来引发另一个textbox的TextChanged事件,从而导致无限递归

如果希望两者都运行一次且仅运行一次,则可以做的第一件事是标记它们已在运行(更改另一个textbox的文本会导致该textbox的事件处理程序在同一调用堆栈中运行:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   if(handler1Running) return; //the second time through we exit immediately
   handler1Running = true;
   ...
   TextBox2.Text = "Something"; //the other event handler is invoked immediately

   handler1Running = false;
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   if(handler2Running) return; //the second time through we exit immediately
   handler2Running = true;
   ...
   TextBox1.Text = "Something Else"; //the other event handler is invoked immediately

   handler2Running = false;
}
现在,它将深入到三个级别:1的处理程序调用2的处理程序,2的处理程序再次调用1的处理程序,该处理程序看到1的处理程序已经在运行,并在执行任何深化递归的操作之前退出。如果从更改TextBox2开始,情况也是如此

您可以做的另一件事是确保您没有尝试将textbox设置为已经存在的相同值。从一个字符串引用更改为另一个字符串引用,即使两个引用都是相同的字符串值,也会触发TextChanged事件。如果递归必须自然继续,但将达到稳定状态,这实际上是第一次要尝试的事情:

public void Textbox1_TextChanged(object sender, EventArgs e)
{
   StringBuilder builder = new StringBuilder();

   ... //build string

   //now, even though the builder's ToString will produce a different reference,
   //we're making sure we don't unnecessarily change the text.
   if(builder.ToString != TextBox2.Text) 
      TextBox2.Text = builder.ToString();       
}

public void Textbox2_TextChanged(object sender, EventArgs e)
{
   StringBuilder builder = new StringBuilder();

   ... //build string

   //now, even though the builder's ToString will produce a different reference,
   //we're making sure we don't unnecessarily change the text.
   if(builder.ToString != TextBox1.Text) 
      TextBox1.Text = builder.ToString();       
}

你能更详细地描述一下你正在解决什么问题吗?我想如果我们有比事件a触发事件B(递归触发事件a)更好的上下文,我们就能给你更好的答案。需要进行一些重新设计。为什么他们互相调用,而不调用任何提供你想要触发的功能的方法?你知道吗