2017-01-03 66 views
0

我在写一个正在触发事件的库。这个库启动第二个连接到服务器并监听消息的线程(阻塞调用,第二个线程的原因)。从第二个线程提升事件到主线程,没有形式

public virtual event LogEventHandler EntryReceived; 

protected virtual void ReceiveEntry(ILogEntry entry) 
{ 
    if (EntryReceived != null) 
     EntryReceived(this, new LogEventArgs() { Entry = entry }); 
} 

当从服务器接收的邮件,它触发一个事件:

ReceiveEntry(entry); 

我想结束developper不要去想了InvokeRequired/Invoke的在他的事件片断处理程序。我如何确保在“父”线程(我知道它与实例化我的类的线程相同)上激发我的事件?

回答

0

为此,有一些winforms元素叫做SynchronizingObject。该属性的类型为ISynchronizeInvoke,它具有在UI线程中执行调用所需的方法。

在你的代码检查此属性无效,如果它被设置你使用它:

var sync = this.SynchronizingObject; 

if (sync != null && sync.InvokeRequired) 
    sync.BeginInvoke(new Action(()=> ReceiveEntry(entry), null); 
else       
    ReceiveEntry(entry); 

库的用户只是要放在一个控制或表单到该属性:

private MyLibraryClass _MyLibraryClass; 

public Form1() 
{ 
    InitializeComponent(); 

    _MyLibraryClass = new MyLibraryClass(); 
    _MyLibraryClass.SynchronizingObject = this; 
    _MyLibraryClass.EntryReceived += OnEntryReceived; 
} 

private void OnEntryReceived(object sender, LogEventArgs e) 
{ 
    myTextBox.Text += e.Entry.Message; 
} 
0

如果对象施工过程中您捕获SynchronizationContext你将能够发送这方面的事件,如果有一个,如果没有背景,然后你的类是建立在这样一个线程在它不关心哪个线程被用来提高事件。这比ISynchronizeInvoke好,因为SynchronizationContext将与WinForms,ASP.NET和WPF一起使用,其中ISynchronizeInvoke仅适用于WinForms。

C#6版本

public class Example 
{ 
    private SynchronizationContext _context; 

    public Example() 
    { 
     var existingContext = SynchronizationContext.Current; 
     _context = existingContext?.CreateCopy() ?? new SynchronizationContext(); 
    } 


    public virtual event LogEventHandler EntryReceived; 

    protected virtual void ReceiveEntry(ILogEntry entry) 
    { 
     _context.Send(ContextCallback, entry); 
    } 

    private void ContextCallback(object entry) 
    { 
     EntryReceived?.Invoke(this, new LogEventArgs() { Entry = (ILogEntry)entry }); 
    } 
} 

C#5和低版本

public class Example 
{ 
    private SynchronizationContext _context; 

    public Example() 
    { 
     var existingContext = SynchronizationContext.Current; 
     _context = existingContext != null ? existingContext.CreateCopy() : new SynchronizationContext(); 
    } 


    public virtual event LogEventHandler EntryReceived; 

    protected virtual void ReceiveEntry(ILogEntry entry) 
    { 
     _context.Send(ContextCallback, entry); 
    } 

    private void ContextCallback(object entry) 
    { 
     var temp = EntryReceived; 
     if (temp != null) 
     { 
      temp(this, new LogEventArgs() {Entry = (ILogEntry)entry}); 
     } 
    } 
}