2011-08-04 27 views
7

Chính xác Control.Invoke (Delegate) làm gì để có được đại biểu chạy trên luồng GUI? Hơn nữa, sự hiểu biết của tôi mà gọi sẽ chặn cho đến khi chức năng gọi nó được thực hiện. Làm thế nào để đạt được điều này?Tò mò về việc thực hiện Control.Invoke()

Tôi muốn có một số chi tiết hữu ích. Tôi hy vọng sẽ học được điều gì đó thú vị.

+0

Kiểm tra [this] [1] out. [1]: http://stackoverflow.com/questions/4514273/does-control-invoke-pump-messages – n8wrl

Trả lời

4

Chỉnh sửa: Bộ điều khiển thực hiện giao diện ISynchronizeInvoke, Bạn có thể tạo hiệu ứng tương tự bằng cách sử dụng SynchronizationContext và gọi Post khi bạn gọi Invoke. cái gì đó như:

public object Invoke(Delegate method, object[] args) 
{ 
    if (method == null) 
    { 
     throw new ArgumentNullException("method"); 
    } 

    object objectToGet = null; 

    SendOrPostCallback invoker = new SendOrPostCallback(
    delegate(object data) 
    { 
     objectToGet = method.DynamicInvoke(args); 
    }); 

    _currentContext.Send(new SendOrPostCallback(invoker), method.Target); 

    return objectToGet; 
} 

Tiếp tục điều tra sử dụng Reflector cho thấy Invoke sử dụng một số API bản địa gọi để đạt được điều đó:

private object MarshaledInvoke(Control caller, Delegate method, object[] args, bool synchronous) 
{ 
    int num; 
    if (!this.IsHandleCreated) 
    { 
     throw new InvalidOperationException(SR.GetString("ErrorNoMarshalingThread")); 
    } 
    if (((ActiveXImpl) this.Properties.GetObject(PropActiveXImpl)) != null) 
    { 
     IntSecurity.UnmanagedCode.Demand(); 
    } 
    bool flag = false; 
    if ((SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, this.Handle), out num) == SafeNativeMethods.GetCurrentThreadId()) && synchronous) 
    { 
     flag = true; 
    } 
    ExecutionContext executionContext = null; 
    if (!flag) 
    { 
     executionContext = ExecutionContext.Capture(); 
    } 
    ThreadMethodEntry entry = new ThreadMethodEntry(caller, this, method, args, synchronous, executionContext); 
    lock (this) 
    { 
     if (this.threadCallbackList == null) 
     { 
      this.threadCallbackList = new Queue(); 
     } 
    } 
    lock (this.threadCallbackList) 
    { 
     if (threadCallbackMessage == 0) 
     { 
      threadCallbackMessage = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_ThreadCallbackMessage"); 
     } 
     this.threadCallbackList.Enqueue(entry); 
    } 
    if (flag) 
    { 
     this.InvokeMarshaledCallbacks(); 
    } 
    else 
    { 
     UnsafeNativeMethods.PostMessage(new HandleRef(this, this.Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero); 
    } 
    if (!synchronous) 
    { 
     return entry; 
    } 
    if (!entry.IsCompleted) 
    { 
     this.WaitForWaitHandle(entry.AsyncWaitHandle); 
    } 
    if (entry.exception != null) 
    { 
     throw entry.exception; 
    } 
    return entry.retVal; 
} 
1

Nếu tôi muốn biết internals, tôi thường cháy lên ILSpy và nhìn vào các nguồn được giải mã của BCL. Ngoài ra, bạn có thể tải xuống các nguồn Mono hoặc Rotor.

+2

Hoặc sử dụng Reflector;) – Abel

+0

Đừng có nói xấu "R" từ! ;-) –

+0

Nếu giấy phép của Reflector thay đổi, tôi bắt đầu sử dụng trình dịch ngược của Telerik và thích nó: http://www.keepdecompilingfree.com – Jamey

Các vấn đề liên quan