C# 从一个事件返回一个值——这有好的实践吗?

C# 从一个事件返回一个值——这有好的实践吗?,c#,multithreading,events,delegates,C#,Multithreading,Events,Delegates,我正在开发一个使用异步TCP套接字的小型多线程应用程序,但我要说的是:我正在使用一个自定义事件从表单读取一个值,事件使用的委托在完成时返回一个字符串 我的问题是:这是正确的吗?可以从事件返回值吗?还是有更好的方法?(就像使用表单的简单委托读取值)我能想到的最接近的例子是WinForms中的FormClosing事件。它允许窗体通过将eventArgs.cancel属性设置为true来取消事件。若要执行类似的操作,可以使用返回值定义自己的event args类作为该类的属性。然后在引发事件时传递事

我正在开发一个使用异步TCP套接字的小型多线程应用程序,但我要说的是:我正在使用一个自定义事件从表单读取一个值,事件使用的委托在完成时返回一个字符串


我的问题是:这是正确的吗?可以从事件返回值吗?还是有更好的方法?(就像使用表单的简单委托读取值)

我能想到的最接近的例子是WinForms中的FormClosing事件。它允许窗体通过将eventArgs.cancel属性设置为true来取消事件。若要执行类似的操作,可以使用返回值定义自己的event args类作为该类的属性。然后在引发事件时传递事件args对象。引发事件的人可以检查事件args对象的返回值。接收事件的其他人也可以检查或更改事件args对象


更新:我刚刚运行了该事件,它似乎是一个返回值的事件。似乎您只需要声明一个返回值的委托类型,然后用该委托类型定义事件。不过,我还没有尝试过创建这样的活动。在事件参数上使用属性的一个优点是,事件的所有订阅者都可以看到以前的订阅者返回的内容。

从事件中返回值通常比较麻烦。在实践中,我发现在传递给事件的一组自定义EventArg上包含一个可写属性,然后在事件激发后检查它要容易得多——类似于WinForms FormClosing事件的Cancel属性。

我认为这不是一个好主意。。。事件基本上是多播委托,因此可以有多个处理程序。在这种情况下,您将采用哪个返回值?

我不知道这是否是最佳做法,但我是这样做的

   Func<DataRow, bool> IsDataValid;

   // some other code ....

   isValid = true;
   if (IsDataValid != null)
   {
      foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
      {
         isValid &= func(Row);
      } 
   }
Func IsDataValid;
//其他一些代码。。。。
isValid=true;
如果(IsDataValid!=null)
{
foreach(IsDataValid.GetInvocationList()中的Func Func)
{
isValid&=func(行);
} 
}
无效方法()
{
列表字符串=新列表();
dostuff+=材料;
dostuff+=材料;
dostuff(这是新的EventHandlerArgs(){Parameter=strings})
foreach(字符串中的字符串currString)
{
//....
}
}
void stuff(对象发送器,EventHandlerArgs e)
{
列表字符串=e.参数为列表;
if(字符串!=null)
{
strings.Add(MyString)
}
}

我知道这篇文章已经发表很久了,但我想用代码添加注释,解释达斯汀·坎贝尔(Dustin Campbell)在别人遇到这篇文章时的回答。我是在决定什么是最佳实践时看到这篇文章的,这就是答案的意思

创建自己的自定义事件处理程序类

public class myCustomeEventArgs:EventArgs
{
    public bool DoOverride { get; set; }
    public string Variable1 { get; private set; }
    public string Variable2{ get; private set; }

    public myCustomeEventArgs(string variable1 , string variable2 )
    {
        DoOverride = false;
        Variable1 = variable1 ;
        Variables = variable2 ;
    }
}
因此,当您创建事件委托时,可以像下面这样使用您创建的事件参数

public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e);
在引发事件的类中,您声明了事件

public event myCustomeEventHandler myCustomeEvent;
因此,当您在类中触发事件时,侦听事件的类可以在事件体中设置e.DoOverride=true;它将在触发事件的类中声明

public event myCustomeEventHandler myCustomeEvent;
火灾事件,例如:

if(myCustomeEvent != null)
{
    var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible");
    myCustomeEvent(this, eventArgs);
    //Here you can now with the return of the event work with the event args
    if(eventArgs.DoOverride)
    {
       //Do Something
    }
}

如果事件返回一个值,并且注册了多个处理程序,则事件将返回上次调用的处理程序的结果值。

中查找示例注意:只有最后一个事件返回结果

class Program
{
static event Func<string, bool> TheEvent;

    static void Main(string[] args)
    {
        TheEvent += new Func<string, bool>(Program_TheEvent);
        TheEvent +=new Func<string,bool>(Program_TheEvent2);
        TheEvent += new Func<string, bool>(Program_TheEvent3);
        var r = TheEvent("s"); //r == flase (Program_TheEvent3)
    }

    static bool Program_TheEvent(string arg)
    {
        return true;
    }

    static bool Program_TheEvent2(string arg)
    {
        return true;
    }

    static bool Program_TheEvent3(string arg)
    {
        return false;
    }        
}
类程序
{
静态事件函数事件;
静态void Main(字符串[]参数)
{
事件+=新函数(程序事件);
事件+=新函数(程序事件2);
事件+=新功能(程序事件3);
var r=TheEvent(“s”);//r==flase(Program\u TheEvent3)
}
静态布尔程序事件(字符串参数)
{
返回true;
}
静态布尔程序\u TheEvent2(字符串arg)
{
返回true;
}
静态布尔程序\u TheEvent3(字符串arg)
{
返回false;
}        
}

我像这样遍历EventArg的属性,并提取其X和Y值

private void navBarControl1\u单击(对象发送方,事件参数e)
{
int x=0;
int _y=0;
类型t=e.GetType();
IList props=新列表(t.GetProperties());
foreach(PropertyInfo props in props)
{
如果(道具名称=“X”)
{
对象propValue=prop.GetValue(e,null);
_x=转换为32(propValue);
}
如果(道具名称=“Y”)
{
对象propValue=prop.GetValue(e,null);
_y=转换为32(propValue);
}
}

能否请您详细说明
在传递给事件部分的一组自定义EventArgs上包含一个可写属性?@Odys使EventArgument对象自定义。创建一个结果存在的属性。欢迎使用stackoverflow!最好提供一个示例代码的简短描述,以提高post准确性:)注意:您可以使用任何委托来定义事件,因此也可以定义类似于
public event Func SomeEvent;
的事件,该事件可调用为
bool r=SomeEvent(“foo”、“bar”);
谢谢。适用于我的WCF服务如何知道事件何时“返回”?事件在引发它们的同一线程上运行。运行
myCustomeEvent(…)
的代码将把控制权(在同一线程上运行)传递给所有订阅的事件处理程序。一旦它们的所有代码都已运行,则控制权将在调用
myCusomeEvent(…)后立即返回指令
。如果没有订阅者,或者有订阅者将事件重新广播到另一个线程上,则
eventArgs
上的所有属性都将有其默认值(对于
bool
为false,对于字符串为
null
)。回答中的链接无效-“未找到页面”。