2009-07-30 52 views
29

我正在做一个使用异步TCP套接字的小型多线程应用程序,但我会注意到:我使用自定义事件从窗体读取值,事件使用的委托返回字符串等结束了。从活动中返回一个值 - 有没有一个好的做法呢?

我的问题在这里是:是正确的?可以从事件返回值吗?还是有更好的方法来做到这一点? (如使用一个简单的代表来读取表单的值)

回答

31

从事件返回值通常很尴尬。在实践中,我发现在传递给事件的一组自定义EventArgs上包含一个可写属性并在事件触发后进行检查变得更容易 - 类似于WinForms FormClosing事件的Cancel属性。

+8

请您详细说明在传递给事件部分的一组自定义EventArgs上包含可写属性? – Odys 2012-10-08 09:00:28

+0

@Oys使EventArgument对象自定义。创建结果所在的属性。 – Crisfole 2016-09-27 14:53:57

15

我能想到的最接近的例子是WinForms中的FormClosing事件。它通过将eventArgs.Cancel属性设置为true来让表单取消该事件。为了做类似的事情,你可以定义你自己的事件参数类和返回值作为该类的属性。然后,每当您提出事件时传递事件参数对象。提出事件的人可以检查事件参数对象的返回值。接收事件的其他人也可以检查或更改事件参数对象。

更新:我刚碰到AppDomain.AssemblyResolve事件,它似乎是一个返回值的事件。看起来你只需要声明一个返回值的委托类型,然后用该委托类型定义事件。不过,我还没有尝试过创建自己的事件。在事件参数上使用属性的一个优点是事件的所有订阅者都可以看到以前的订阅者返回了哪些内容。

+1

注意:您可以使用任何委托定义事件,因此定义一个类似`public event Func SomeEvent;`的事件也可以,它可以被调用为`bool r = SomeEvent(“foo”,“bar”);` – 2012-11-22 02:15:43

26

我不认为这是一个好主意......事件基本上是多播委托,所以可以有多个处理程序。在这种情况下你会拿哪个回报值?

6

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

Func<DataRow, bool> IsDataValid; 

    // some other code .... 

    isValid = true; 
    if (IsDataValid != null) 
    { 
     foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList()) 
     { 
     isValid &= func(Row); 
     } 
    } 
-1
void method() 
{ 
    list<string> strings = new list<string>(); 

    dostuff += stuff; 
    dostuff += stuff; 

    dostuff(this, new EventHandlerArgs(){ Parameter = strings }) 

    foreach(string currString in strings) 
    { 
      //.... 
    } 
} 

void stuff(object sender, EventHandlerArgs e) 
{ 
    list<string> strings = e.Parameter as list<string>; 

    if (strings != null) 
    { 
     strings.Add(MyString) 
    } 
} 
+2

欢迎来到计算器!最好提供一个示例代码的简短描述以提高帖子的准确性:) – 2012-11-04 12:45:04

10

我知道这是后但添加注释的代码解释达斯汀·坎贝尔的答案,如果别人遇到这个线程的想法后,年龄。我在试图确定什么是最佳实践时遇到了这篇文章,这就是答案的意思。

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

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;因为它将在课堂上宣布该事件。

例如火灾事件:

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 
    } 
} 
+0

你怎么知道事件何时会“返回”? – 2015-11-13 18:39:06

+4

事件在引发它们的同一个线程上运行。运行`myCustomeEvent(...)`的代码会将控制权(在同一个线程上运行)传递给所有订阅的事件处理程序。一旦所有的代码都运行完毕,那么在调用`myCusomeEvent(...)`后,控制权将立即返回到指令。如果没有订阅者,或者有订阅者将事件重播到另一个线程,那么`eventArgs`上的所有属性都将具有其默认值(对于字符串,“bool”和“null”为false)。 – 2016-01-08 22:25:04

6

注意:只有最后一个事件返回结果。

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; 
    }   
} 
0

我循环这样的EventArgs的属性,并提取其X和Y值。

private void navBarControl1_Click(object sender,EventArgs e) { int _x = 0; int _y = 0;

 Type t = e.GetType(); 
     IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties()); 

     foreach (PropertyInfo prop in props) 
     { 
      if (prop.Name == "X") 
      { 
       object propValue = prop.GetValue(e, null); 
       _x = Convert.ToInt32(propValue); 
      } 
      if (prop.Name == "Y") 
      { 
       object propValue = prop.GetValue(e, null); 
       _y = Convert.ToInt32(propValue); 
      } 
     } 
相关问题