2017-01-03 89 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}); 
     } 
    } 
}