2017-01-03 1 views
0

이벤트를 발생시키는 라이브러리를 쓰고 있습니다. 이 라이브러리는 서버에 연결하고 메시지를 수신하는 두 번째 스레드를 시작합니다 (두 번째 스레드의 이유, 호출 차단).양식없이 두 번째 스레드에서 주 스레드로 이벤트 발생

ReceiveEntry(entry); 

내가 InvokeRequired/호출에 대해 생각해야하지 developper 끝을 좋아하는 자신의 이벤트에 니펫을 것 :

메시지가 서버로부터 수신
public virtual event LogEventHandler EntryReceived; 

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

,이 이벤트를 발사한다 매니저. "부모"스레드 (내 클래스를 인스턴스화 한 스레드와 동일하다는 것을 알고 있습니다)에서 내 이벤트를 실행할 수 있도록하려면 어떻게해야합니까?

답변

0

일부 winforms 요소에는 SynchronizingObject이라는 속성이 있습니다. 이 속성은 UI 스레드 내에서 호출을 실행하는 데 필요한 메서드가있는 ISynchronizeInvoke 유형입니다. 코드에서

당신은 무효에 대해이 속성을 확인하고 설정되어있는 경우 당신은 그것을 사용

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은 WinForms, ASP.NET 및 WPF에서 작동하기 때문에 ISynchronizeInvoke보다 낫습니다. 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}); 
     } 
    } 
} 
관련 문제